Install
openclaw skills install twitter-thread-schedulerPost native X/Twitter threads by chaining reply-to calls via Twitter API v2. Buffer cannot post threads — use this for any multi-tweet X content from the content pipeline.
openclaw skills install twitter-thread-schedulerBuffer's GraphQL API has no thread field — it only supports single posts. To post a proper X thread (tweet 1 → reply → reply → ...), you need direct Twitter API v2 access.
This script uses the redditech OAuth2 credentials from ~/.xurl to:
reply: { in_reply_to_tweet_id: <id> } — get tweet 2's IDmemory/thread-log.jsonlThis is the ONLY way to schedule real X threads. Always use this script over Buffer for multi-tweet content.
scripts/tweet_thread_scheduler.py
Auth: ~/.xurl → apps.redditech.users.redditech.access_token (auto-refreshes on 401)
python3 scripts/tweet_thread_scheduler.py preview \
--file projects/social-growth/thread-<slug>.md
Run this first. Confirms tweet count and flags any over 280 chars.
python3 scripts/tweet_thread_scheduler.py post \
--file projects/social-growth/thread-<slug>.md \
--slug <slug>
# Prompts for confirmation before posting
python3 scripts/tweet_thread_scheduler.py post \
--file projects/social-growth/thread-<slug>.md \
--slug <slug> \
--dry-run
python3 scripts/tweet_thread_scheduler.py schedule \
--file projects/social-growth/thread-<slug>.md \
--slug <slug> \
--at "2026-04-05T08:00:00+11:00"
# Writes queue file + creates `at` job
at)python3 scripts/tweet_thread_scheduler.py fire \
--queue memory/thread-queue/<slug>.json
The script parses the blog-to-social output format automatically:
## Thread (9 tweets)
[1/9] First tweet text here.
[2/9] Second tweet text here.
...
[9/9] Final tweet with blog URL. #Hashtag1 #Hashtag2
Also supports ## Tweet N headers and --- dividers.
Always run preview before scheduling to confirm parsing is correct.
| Path | Purpose |
|---|---|
memory/thread-queue/<slug>.json | Queued thread data (tweets + schedule time) |
memory/thread-log.jsonl | Posted threads — all tweet IDs + URLs |
In the blog-to-social and blog-publish playbooks:
projects/social-growth/thread-<slug>.mdpreview to verify parsing[BLOG_URL] placeholder before schedulingschedule --at <publishAt + 15min> to align with blog embargo timingscripts/buffer-post.mjsRule: Buffer for LinkedIn. This script for X threads.
2026-04-03 — First use (portkey-patterns + ollama-embeddings):
createPost with thread field returns GRAPHQL_VALIDATION_FAILED — field doesn't existreply fieldat scheduling works cleanly — jobs survive across sessions[1/N] formatBuffer delete API (corrected 2026-04-03):
id (NOT postId)DeletePostSuccess { id } | VoidMutationError { message } (NOT PostActionSuccess)createPost which uses PostActionSuccess