Every day, fan out (syndicate) the latest WeChat official account article that hasn't been distributed yet to each social platform.One set of copy for everywhere, for those with an API actually post it, for those without an API prepare an outbox for you to paste manually.
Core Principles
- Stability first: each platform is an independent step; one failure never affects the others.
- Idempotent deduplication:
state/history.jsonlby(slug, platform)records; re-running only sends what didn't succeed, never posts twice. - Credential degradation: API platform missing/expired credentials → automatically switch to outbox (manual), without erroring.
- Signature / CTA uses "Wang Jianshuo"(user's global preference), no marketing tone, no piling on hashtags/@/emoji (unless the original has them).
Inputs
/wjs-syndicating-articles # 选最新未分发文章,走完整流程(默认/定时用)
/wjs-syndicating-articles <article-folder># 显式指定文章
/wjs-syndicating-articles --open # 交互模式:打开手动平台 web 页 + 文案进剪贴板
/wjs-syndicating-articles --dry-run # 只草拟,不发、不写 history
/wjs-syndicating-articles --mark <slug> <platform> # 手动标记某平台已发
SKILL_DIR = ~/.claude/skills/wjs-syndicating-articles
Workflow (default / scheduled run)
Step 0: --mark short-circuit
If the call is --mark <slug> <platform>:bash $SKILL_DIR/scripts/history.sh record <slug> <platform> posted then tell the user it has been marked, and end.
Step 1: Select article
bash $SKILL_DIR/scripts/pick-next-article.sh
- If explicitly specified
<article-folder>then skip this script and use it directly. - Output is empty → all recent articles have been distributed, today is a rest day, end.
- Record
FOLDER,SLUG=$(basename "$FOLDER")。
Step 2: Extract one set of core copy (you do this, not the script)
Read $FOLDER/article.md and $FOLDER/meta.json. Extractone most quotable core sentence/short paragraph, ≤120 characters(ensure it fits in X's 280 characters; each Chinese character counts as 2), keeping Wang Jianshuo's tone. Then add one line of soft CTA + article link (WeChat official account link, if none use the info in meta.json + article_url_base)。
Write the final copy into $SKILL_DIR/outbox/<date>-<SLUG>/post.txt(first mkdir -p)。<date>=$(date +%F)。
--dry-run when: print the post.txt content + "what will be posted" for each platform below,do notcontinue to Step 3+, end.
Step 3: Fan out (handled by one deterministic script, LLM doesn't touch keys)
bash $SKILL_DIR/scripts/syndicate.sh "$FOLDER" "$POST_TXT"
syndicate.sh Internally: slug is always taken as basename "$FOLDER"; API platforms (X/Bluesky/Threads/LinkedIn) each try/catch to actually post, X will first check the tweeting skill's history to prevent double posting, missing credentials automatically degrade and record queued; manual platforms (Facebook/Xiaohongshu/Jike/Zhihu) call build-outbox.sh to prepare outbox/<slug>/ and record queued。Do not hand-write the platform loop or assemble the slug yourself — leave it all to the script, to avoid key drift.--dry-run when, instead run syndicate.sh "$FOLDER" "$POST_TXT" --dry-run(doesn't post, doesn't write history). Each line of the script's stdout <platform>: ... and the trailing outbox=... are the data source for the Step 5 summary.
Step 5: Notify + summarize
Print a table: each platform's status (posted+URL / queued(outbox) / failed / skipped).
Unattended (scheduled) run: send a PushNotification, e.g.: "✅ X, Bluesky posted; 📋 Facebook/Xiaohongshu/Jike/Zhihu waiting in outbox to paste: $OUTBOX".
Do notautomatically open the browser in Step 5 — that is --open 's job.
--open mode (interactive, when posting to manual platforms)
- Find today's outbox:
$SKILL_DIR/outbox/$(date +%F)-<SLUG>(or the latest one). cat OUTBOX/post.txt | pbcopy(copy goes to clipboard).- Use the
/browseskill to open theweb_compose。 - Xiaohongshu:
open "$OUTBOX/image.png"(Finder pops up), prompting the user to AirDrop to the phone; the copy is already in the clipboard. - Prompt one by one: paste → publish. After the user finishes posting a certain available
--mark <slug> <platform>。
File Layout
$SKILL_DIR/
├── SKILL.md config.json secrets.json(gitignored)
├── scripts/ lib.sh history.sh pick-next-article.sh post-*.sh build-outbox.sh
├── outbox/<date>-<slug>/ post.txt image.png OPEN.md
└── state/history.jsonl
Configure API platforms (optional; only actually posts if configured)
Copy secrets.json.example → secrets.json, fill in bluesky / threads / linkedin as needed. Platforms left unfilled automatically go to outbox.
Daily automation
/schedule daily 10:00 /wjs-syndicating-articles