The missing CLI for social posting — YouTube, Instagram, Facebook, X, LinkedIn.
Built for humans and AI agents. Zero dependencies. Auditable by design.
curl -fsSL https://post-ctl.pages.dev/install.sh | sh
npm i -g post-ctl # package post-ctl · command postctl
bunx post-ctl --version
macOS & Linux (arm64/x64) prebuilt. Windows via npm.
postctl setup youtube
Walks you through the Google Cloud project, consent screen, and OAuth client, then logs you in and verifies your channel. Re-runnable and resumable.
postctl validate "My talk" --media ./talk.mp4 --account isha
postctl post "My talk" --media ./talk.mp4 \ --description ./notes.txt --tags "wisdom,talk" --account isha
Everything speaks JSON when stdout isn't a TTY (or with --output json), and the exit code is the contract — no output parsing needed to branch.
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | validation / API failure |
| 4 | auth required — run auth login |
# dry-run first; only post if the payload validates if postctl validate "$TITLE" --media "$FILE" --account isha; then postctl post "$TITLE" --media "$FILE" --account isha --output json > result.json else echo "invalid, skipping" >&2 fi
# exit 1 if any account/token/staging check fails
postctl doctor --output json | jq -e '.[] | select(.status=="fail")' && exit 1 || true
# 09:00 daily — tokens refresh silently; no interaction in the write path
0 9 * * * /usr/bin/env postctl post "$(cat /srv/today.txt)" \
--media /srv/clip.mp4 --account isha --output json \
>> /var/log/postctl.log 2>&1