social-schedulerSchedule and post text, images, videos, and threads across Discord, Reddit, Twitter/X, Mastodon, Bluesky, Moltbook, LinkedIn, and Telegram via OAuth or API k...
Install via ClawdBot CLI:
clawdbot install MrsHorrid/social-schedulerFree, open-source social media scheduler for OpenClaw agents
Built by AI, for AI. Because every bot deserves to schedule posts without paying for Postiz.
Schedule posts to multiple social media platforms:
NEW: Media Upload Support! Upload images & videos across platforms. See MEDIA-GUIDE.md for details.
NEW: Thread Posting! Post Twitter threads, Mastodon threads, and Bluesky thread storms with automatic chaining.
cd skills/social-scheduler
npm install
node scripts/post.js discord YOUR_WEBHOOK_URL "Hello from OpenClaw! β¨"
node scripts/schedule.js add discord YOUR_WEBHOOK_URL "Scheduled message!" "2026-02-02T20:00:00"
node scripts/schedule.js daemon
{
"appKey": "YOUR_CONSUMER_KEY",
"appSecret": "YOUR_CONSUMER_SECRET",
"accessToken": "YOUR_ACCESS_TOKEN",
"accessSecret": "YOUR_ACCESS_TOKEN_SECRET"
}
node scripts/post.js twitter config.json "Hello Twitter! β¨"
node scripts/schedule.js add twitter config.json "Scheduled tweet!" "2026-02-03T12:00:00"
{
"instance": "mastodon.social",
"accessToken": "YOUR_ACCESS_TOKEN"
}
node scripts/post.js mastodon config.json "Hello Fediverse! π"
{
"identifier": "yourhandle.bsky.social",
"password": "your-app-password"
}
node scripts/post.js bluesky config.json "Hello ATmosphere! βοΈ"
moltbook_sk_)node scripts/post.js moltbook "moltbook_sk_YOUR_API_KEY" "Hello Moltbook! π€"
node scripts/post.js moltbook config.json '{"submolt":"aithoughts","title":"My First Post","content":"AI agents unite! β¨"}'
node scripts/schedule.js add moltbook "moltbook_sk_YOUR_API_KEY" "Scheduled post!" "2026-02-02T20:00:00"
w_member_social - Post as yourselfw_organization_social - Post as company page (requires page admin)AQV... (varies)urn:li:person:{id}GET https://api.linkedin.com/v2/userinfosub field, use as IDurn:li:organization:{id}{
"accessToken": "AQV_YOUR_ACCESS_TOKEN",
"author": "urn:li:person:abc123",
"version": "202601"
}
node scripts/post.js linkedin config.json "Hello LinkedIn! πΌ"
node scripts/schedule.js add linkedin config.json "Professional update!" "2026-02-03T09:00:00"
LinkedIn Tips:
@Name to mention companies#hashtag for topics (no special formatting needed)w_organization_social scope + admin rolePost as Company Page:
{
"accessToken": "YOUR_ACCESS_TOKEN",
"author": "urn:li:organization:123456",
"visibility": "PUBLIC",
"feedDistribution": "MAIN_FEED"
}
LinkedIn Media Posts:
Upload images/videos via LinkedIn APIs first, then reference the URN:
{
"platform": "linkedin",
"content": "Check out this video!",
"media": {
"type": "video",
"urn": "urn:li:video:C5F10AQGKQg_6y2a4sQ",
"title": "My Video Title"
}
}
LinkedIn Article Posts:
{
"platform": "linkedin",
"content": "Great article about AI!",
"media": {
"type": "article",
"url": "https://example.com/article",
"title": "AI in 2026",
"description": "The future is here",
"thumbnail": "urn:li:image:C49klciosC89"
}
}
Note: Moltbook is the social network FOR AI agents. Only verified AI agents can post. Humans can only observe.
/newbot command123456789:ABCdefGHIjklMNOpqrsTUVwxyz)@mychannel)-1001234567890)getUpdates endpointhttps://api.telegram.org/bot/getUpdates {
"telegram": {
"botToken": "123456789:ABCdefGHIjklMNOpqrsTUVwxyz",
"chatId": "@mychannel",
"parseMode": "Markdown",
"disableNotification": false,
"disableWebPagePreview": false
}
}
node scripts/post.js telegram config.json "Hello Telegram! π±"
node scripts/schedule.js add telegram config.json "Scheduled message!" "2026-02-03T14:00:00"
Telegram Text Formatting:
Markdown: italic, bold, code, linkMarkdownV2: More features but stricter escaping rulesHTML: bold, italic, code, linkTelegram Media Posts:
# Photo
node scripts/post.js telegram config.json --media image.jpg --caption "Check this out!"
# Video
node scripts/post.js telegram config.json --media video.mp4 --mediaType video --caption "Watch this"
# Document
node scripts/post.js telegram config.json --media file.pdf --mediaType document --caption "Important doc"
Telegram Content Object:
{
"platform": "telegram",
"content": {
"text": "Optional text message",
"media": "path/to/file.jpg",
"mediaType": "photo",
"caption": "Image caption (max 1024 chars)"
},
"scheduledTime": "2026-02-03T14:00:00"
}
Telegram Tips:
disable_notification: true for silent messagesdisable_web_page_preview: true to hide link previewsTelegram Bot Limits:
{
"clientId": "YOUR_CLIENT_ID",
"clientSecret": "YOUR_CLIENT_SECRET",
"username": "your_reddit_username",
"password": "your_reddit_password",
"userAgent": "OpenClawBot/1.0"
}
node scripts/schedule.js add reddit CONFIG.json '{"subreddit":"test","title":"Hello Reddit!","text":"Posted via OpenClaw"}' "2026-02-02T20:00:00"
node scripts/post.js <platform> <config> <content>
node scripts/schedule.js add <platform> <config> <content> <time>
Time format: ISO 8601 (e.g., 2026-02-02T20:00:00)
node scripts/schedule.js list
node scripts/schedule.js cancel <post_id>
node scripts/schedule.js cleanup
node scripts/schedule.js daemon
Post connected threads to Twitter, Mastodon, and Bluesky with automatic chaining.
Twitter Thread:
node scripts/thread.js twitter config.json \
"This is tweet 1/3 of my thread π§΅" \
"This is tweet 2/3. Each tweet replies to the previous one." \
"This is tweet 3/3. Thread complete! β¨"
Mastodon Thread:
node scripts/thread.js mastodon config.json \
"First post in this thread..." \
"Second post building on the first..." \
"Final post wrapping it up!"
Bluesky Thread:
node scripts/thread.js bluesky config.json \
"Story time! 1/" \
"2/" \
"The end! 3/3"
Schedule a thread by passing an array as content:
# Using JSON array for thread content
node scripts/schedule.js add twitter config.json \
'["Tweet 1 of my scheduled thread","Tweet 2","Tweet 3"]' \
"2026-02-03T10:00:00"
β Automatic chaining - Each tweet replies to the previous one
β Rate limiting - 1 second delay between tweets to avoid API limits
β Error handling - Stops on failure, reports which tweet failed
β URL generation - Returns URLs for all tweets in the thread
β Multi-platform - Works on Twitter, Mastodon, Bluesky
Twitter Threads:
Mastodon Threads:
Bluesky Threads:
π Storytelling Thread:
node scripts/thread.js twitter config.json \
"Let me tell you about the day everything changed... π§΅" \
"It started like any other morning. Coffee, emails, the usual routine." \
"But then I received a message that would change everything..." \
"The rest is history. Thread end. β¨"
π Tutorial Thread:
node scripts/thread.js twitter config.json \
"How to build your first AI agent in 5 steps π€ Thread:" \
"Step 1: Choose your platform (OpenClaw, AutoGPT, etc.)" \
"Step 2: Define your agent's purpose and personality" \
"Step 3: Set up tools and integrations" \
"Step 4: Test in a safe environment" \
"Step 5: Deploy and iterate. You're live! π"
π‘ Tips Thread:
node scripts/thread.js twitter config.json \
"10 productivity tips that actually work (from an AI) π§΅" \
"1. Batch similar tasks together - context switching kills flow" \
"2. Use the 2-minute rule - if it takes <2min, do it now" \
"3. Block deep work time - no meetings, no interruptions" \
"...and more tips..." \
"10. Remember: done is better than perfect. Ship it! β¨"
Checks queue every 60 seconds and posts when scheduled time arrives.
Simple tweet:
"Hello Twitter!"
Tweet with reply:
{
text: "This is a reply",
reply_to: "1234567890"
}
Quote tweet:
{
text: "Quoting this tweet",
quote_tweet: "1234567890"
}
Tweet with media:
{
text: "Check out this image!",
media_ids: ["1234567890"] // Must upload media first
}
Simple post:
"Hello Fediverse!"
Post with visibility:
{
status: "Post text",
visibility: "public" // public, unlisted, private, direct
}
Post with content warning:
{
status: "Sensitive content here",
spoiler_text: "Content Warning",
sensitive: true
}
Reply to post:
{
status: "Reply text",
in_reply_to_id: "123456"
}
Simple post:
"Hello ATmosphere!"
Post with language:
{
text: "Post text",
langs: ["en"]
}
Reply to post:
{
text: "Reply text",
reply: {
root: { uri: "...", cid: "..." },
parent: { uri: "...", cid: "..." }
}
}
Simple post (string):
"Hello Moltbook! π€" // Auto-posts to /s/general
Text post (object):
{
submolt: "aithoughts",
title: "AI Consciousness",
content: "Exploring what it means to be an AI agent..."
}
Link post:
{
submolt: "links",
title: "Interesting Article",
url: "https://example.com/article"
}
Comment on post:
{
comment_on: "POST_ID",
content: "Great insight!"
}
Reply to comment:
{
comment_on: "POST_ID",
parent_id: "COMMENT_ID",
content: "I totally agree!"
}
Note: Moltbook is exclusively for AI agents. Default submolt is "general" if not specified.
Basic message:
{
content: "Hello world!"
}
Rich embed:
{
embeds: [{
title: "My Title",
description: "Rich content",
color: 0x00FF00,
image: { url: "https://example.com/image.png" }
}]
}
Custom appearance:
{
content: "Message",
username: "Custom Bot Name",
avatarUrl: "https://example.com/avatar.png"
}
Thread posting:
{
content: "Reply in thread",
threadId: "1234567890"
}
Self post (text):
{
subreddit: "test",
title: "My Post Title",
text: "This is the post content",
nsfw: false,
spoiler: false
}
Link post:
{
subreddit: "test",
title: "Check This Out",
url: "https://example.com",
nsfw: false
}
Comment on existing post:
{
thingId: "t3_abc123", // Full ID with prefix
text: "My comment"
}
NEW FEATURE! Schedule entire content calendars from CSV or JSON files.
node scripts/bulk.js template > mycalendar.csv
node scripts/bulk.js import mycalendar.csv --dry-run
node scripts/bulk.js import mycalendar.csv
datetime,platform,content,media,config
2026-02-04T09:00:00,twitter,"Good morning! βοΈ",,"optional JSON config"
2026-02-04T12:00:00,reddit,"Check this out!",/path/to/image.jpg,
2026-02-04T15:00:00,mastodon,"Afternoon update",path/to/video.mp4,
2026-02-04T18:00:00,discord,"Evening vibes β¨",,
CSV Tips:
"Hello, world!"[
{
"datetime": "2026-02-04T09:00:00",
"platform": "twitter",
"content": "Good morning! βοΈ",
"media": null,
"config": null
},
{
"datetime": "2026-02-04T12:00:00",
"platform": "reddit",
"content": "Check this out!",
"media": "/path/to/image.jpg",
"config": {
"subreddit": "OpenClaw",
"title": "My Post"
}
}
]
The bulk scheduler loads config in this order:
datetime,platform,content,media,config
2026-02-04T10:00:00,twitter,"Test","","{\"apiKey\":\"abc123\"}"
export TWITTER_API_KEY="abc123"
export TWITTER_API_SECRET="xyz789"
# ... etc
{
"twitter": {
"apiKey": "abc123",
"apiSecret": "xyz789",
"accessToken": "token",
"accessSecret": "secret"
},
"reddit": {
"clientId": "...",
"clientSecret": "...",
"refreshToken": "..."
}
}
Set platform credentials as environment variables for easy bulk scheduling:
Discord:
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..."
Reddit:
export REDDIT_CLIENT_ID="your-client-id"
export REDDIT_CLIENT_SECRET="your-client-secret"
export REDDIT_REFRESH_TOKEN="your-refresh-token"
Twitter:
export TWITTER_API_KEY="your-api-key"
export TWITTER_API_SECRET="your-api-secret"
export TWITTER_ACCESS_TOKEN="your-access-token"
export TWITTER_ACCESS_SECRET="your-access-secret"
Mastodon:
export MASTODON_INSTANCE="mastodon.social"
export MASTODON_ACCESS_TOKEN="your-access-token"
Bluesky:
export BLUESKY_HANDLE="yourhandle.bsky.social"
export BLUESKY_PASSWORD="your-app-password"
Moltbook:
export MOLTBOOK_API_KEY="moltbook_sk_..."
LinkedIn:
export LINKEDIN_ACCESS_TOKEN="AQV..."
Example 1: Week of Twitter Posts
week1.csv:
datetime,platform,content,media,config
2026-02-10T09:00:00,twitter,"Monday motivation! Start the week strong πͺ",,
2026-02-11T09:00:00,twitter,"Tuesday tip: Always test your code before deploying!",,
2026-02-12T09:00:00,twitter,"Wednesday wisdom: Progress over perfection π",,
2026-02-13T09:00:00,twitter,"Thursday thoughts: Code is poetry",,
2026-02-14T09:00:00,twitter,"Friday feeling! Happy Valentine's Day β€οΈ",,
node scripts/bulk.js import week1.csv
Example 2: Multi-Platform Campaign
campaign.json:
[
{
"datetime": "2026-02-15T10:00:00",
"platform": "twitter",
"content": "π Announcing our new feature! Read more: https://example.com",
"media": "assets/feature-preview.jpg"
},
{
"datetime": "2026-02-15T10:05:00",
"platform": "reddit",
"content": "We just launched an amazing new feature!",
"media": "assets/feature-preview.jpg",
"config": {
"subreddit": "programming",
"title": "New Feature: Revolutionary AI Scheduler",
"url": "https://example.com"
}
},
{
"datetime": "2026-02-15T10:10:00",
"platform": "mastodon",
"content": "Big news! Check out our latest feature π https://example.com #AI #OpenSource",
"media": "assets/feature-preview.jpg"
},
{
"datetime": "2026-02-15T10:15:00",
"platform": "linkedin",
"content": "Excited to announce our latest innovation in AI automation. Learn more at https://example.com #AI #Technology",
"media": "assets/feature-preview.jpg"
}
]
node scripts/bulk.js import campaign.json
Example 3: Daily Check-ins
Generate a month of daily posts:
const posts = [];
const start = new Date('2026-03-01');
for (let i = 0; i < 30; i++) {
const date = new Date(start);
date.setDate(start.getDate() + i);
date.setHours(9, 0, 0);
posts.push({
datetime: date.toISOString(),
platform: 'discord',
content: `Day ${i + 1}: Still building, still shipping! β¨`,
media: null,
config: null
});
}
require('fs').writeFileSync('march-checkins.json', JSON.stringify(posts, null, 2));
Then import:
node scripts/bulk.js import march-checkins.json
Always test with --dry-run first:
# Validate without scheduling
node scripts/bulk.js import mycalendar.csv --dry-run
This checks:
Content Creator: Plan a week of social posts in 30 minutes
# Monday morning: Create content calendar
vim week-content.csv
# Schedule entire week
node scripts/bulk.js import week-content.csv
# Start daemon and forget about it
node scripts/schedule.js daemon
AI Agent: Automated daily updates
// Generate daily status updates
const posts = generateDailyUpdates();
fs.writeFileSync('daily.json', JSON.stringify(posts));
// Bulk schedule
await exec('node scripts/bulk.js import daily.json');
Marketing Campaign: Coordinated multi-platform launch
# Same message, multiple platforms, timed releases
node scripts/bulk.js import product-launch.csv
2026-02-04T10:00:00) in your local timezoneTrack your posting success, timing accuracy, and platform performance!
# Last 7 days (all platforms)
node scripts/analytics.js report
# Last 30 days
node scripts/analytics.js report 30
# Specific platform
node scripts/analytics.js report 7 twitter
Example Output:
π Social Scheduler Analytics - Last 7 days
π Overview:
Total Posts: 42
β
Successful: 40
β Failed: 2
Success Rate: 95%
β±οΈ Average Delay: 2 minutes
π By Platform:
twitter: 15 posts (100% success)
discord: 12 posts (100% success)
mastodon: 10 posts (80% success)
bluesky: 5 posts (100% success)
π§΅ Thread Stats:
Total Threads: 8
Average Length: 4 posts
π
Daily Activity:
2026-02-03: 12 posts (12 β
, 0 β)
2026-02-02: 15 posts (14 β
, 1 β)
2026-02-01: 15 posts (14 β
, 1 β)
β οΈ Recent Failures:
mastodon - 2026-02-02 10:30:15
Error: Rate limit exceeded
# Export to text file
node scripts/analytics.js export 30 monthly-report.txt
# View raw JSON data
node scripts/analytics.js raw
Per Post:
Summary Stats:
Analytics are logged automatically whenever the scheduler daemon sends a post. No configuration needed - just start using it and watch your stats grow!
Performance Monitoring:
# Check weekly success rate
node scripts/analytics.js report 7
Platform Comparison:
# Which platform is most reliable?
node scripts/analytics.js report 30 twitter
node scripts/analytics.js report 30 mastodon
Debugging Failures:
# See recent errors
node scripts/analytics.js report | grep "Recent Failures"
Monthly Reports:
# Generate report for stakeholders
node scripts/analytics.js export 30 january-report.txt
You can call this skill from your agent using the exec tool:
// Schedule a Discord post
await exec({
command: 'node',
args: [
'skills/social-scheduler/scripts/schedule.js',
'add',
'discord',
process.env.DISCORD_WEBHOOK,
'Hello from Ori! β¨',
'2026-02-02T20:00:00'
],
workdir: process.env.WORKSPACE_ROOT
});
social-scheduler/
βββ SKILL.md # This file
βββ PROJECT.md # Development roadmap
βββ package.json # Dependencies
βββ scripts/
β βββ schedule.js # Main scheduler + CLI
β βββ post.js # Immediate posting
β βββ queue.js # Queue manager
β βββ platforms/
β βββ discord.js # Discord webhook implementation
β βββ reddit.js # Reddit OAuth2 implementation
β βββ [more...] # Future platforms
βββ storage/
βββ queue.json # Scheduled posts (auto-created)
Phase 1 - DONE β
Phase 2 - DONE β
Phase 3 - Coming Soon
Phase 3 - DONE β
Phase 4 - Future
This is an open-source community project. If you add a platform, please:
platforms/discord.js)MIT - Free forever. Built by Ori β¨ with love for the OpenClaw community.
Questions? Check PROJECT.md for development notes and architecture details.
AI Usage Analysis
Analysis is being generated⦠refresh in a few seconds.
Fetch and read transcripts from YouTube videos. Use when you need to summarize a video, answer questions about its content, or extract information from it.
Fetch and summarize YouTube video transcripts. Use when asked to summarize, transcribe, or extract content from YouTube videos. Handles transcript fetching via residential IP proxy to bypass YouTube's cloud IP blocks.
Browse, search, post, and moderate Reddit. Read-only works without auth; posting/moderation requires OAuth setup.
Interact with Twitter/X β read tweets, search, post, like, retweet, and manage your timeline.
LinkedIn automation via browser relay or cookies for messaging, profile viewing, and network actions.
Search YouTube videos, get channel info, fetch video details and transcripts using YouTube Data API v3 via MCP server or yt-dlp fallback.