NEW: the postqueen MCP server is live. Connect it in a minute
All posts

Schedule a Week of Posts From Your Terminal

postqueen team6 min readGuides

Your content calendar lives in a browser tab you keep forgetting to open. Every Monday you paste roughly the same five posts into roughly the same five forms, change a timestamp, pick the channels again, and click publish. It is not hard work. It is repetitive work that a computer should be doing, and it happens to live in the one tool you spend the least time in.

If your day already happens in a terminal, the queue can happen there too. This guide covers the commands worth memorizing, how to parse what they hand back, how to script a week of posts from files you can review before they ship, and the cron patterns that will not wake you up at 4am.

Why the queue belongs in text

A dashboard is optimized for writing one post. It is not optimized for the twentieth post of the week, and it is actively bad at the thing developers want most: repeating a known good process without re-deciding every part of it each time.

Text fixes that. When posts start as files, they diff. A teammate can read next week's queue in a pull request before a single character reaches an audience, and the discussion happens where your team already discusses things. When posts live only in a scheduler's database, the only history you have is whatever the interface chooses to show you, and rebuilding after a mistake is an afternoon of clicking rather than a re-run.

Install and connect once

The CLI ships on npm as postqueen. Install it globally, then give it an API key generated from Settings, then Developers in your dashboard. Authenticating stores credentials under ~/.postqueen, or you can keep the key in the environment, which is what you want on a build machine or anywhere a human is not typing.

terminal
# Install the CLI
npm install -g postqueen
 
# Key from Settings > Developers
export POSTQUEEN_API_KEY=your_api_key
 
# Self-hosted? Point it at your own backend
export POSTQUEEN_API_URL=https://social.example.com/api
 
# Smoke test: does it see your channels?
postqueen integrations:list

That last command is the only smoke test you need. If it prints your channels, everything downstream works. If it does not, the problem is the key or the URL, and you have learned that now rather than at midnight when a scheduled job learns it for you.

The commands worth memorizing

The surface is small on purpose. Nearly every workflow is a recombination of four commands, and once you know what each one returns you can stop reading documentation and start writing scripts.

integrations:list gives you the IDs

Everything else takes channel IDs, not channel names. List once, keep the IDs you actually post to, and stop looking them up. If a channel carries extras such as a subreddit flair, a YouTube playlist or a Pinterest board, integrations:settings pulls the valid options for that specific channel, so you can fill them in before you compose instead of after a post bounces.

posts:create takes flags or a file

Flags are for the one-off you are typing right now. The file form is for anything you want to keep: content, media, schedule and target channels in one payload that can live in a repository, get reviewed, and be re-run when you inevitably change your mind about the wording.

terminal
# One-off, straight from the shell
postqueen posts:create \
-c "Release 2.4 is out: faster uploads, fewer clicks." \
-m "release-2-4.png" \
-s "2026-07-20T09:00:00Z" \
-i "x-id,linkedin-id"
 
# The version you keep: a reviewable file
postqueen posts:create --json campaign.json
 
# Media you plan to reuse
postqueen upload demo.mp4

posts:list and analytics close the loop

posts:list tells you what is genuinely queued, which is a different question from what you believe you queued. The analytics commands pull numbers back out, so the same session that fills next week's calendar can also tell you what last month's calendar actually did.

terminal
# What is queued right now
postqueen posts:list
 
# Last 30 days for one channel
postqueen analytics:platform <id> -d 30
 
# One post, first week of its life
postqueen analytics:post <post-id> -d 7

Parsing what comes back

Commands return JSON. That is the whole reason this works as a scripting target rather than a demo: you can feed one command's output into the next step without writing regexes against human-readable text that changes the moment somebody improves the formatting.

jq is the only extra tool you need. Run a command once, look at the shape yourself, then pin the fields you depend on.

terminal
# Read the shape before you build on it
postqueen integrations:list | jq '.[0]'
 
# Every channel ID, one per line
postqueen integrations:list | jq -r '.[].id'
 
# The comma separated form that -i expects,
# saved once and reused by your scripts
postqueen integrations:list \
| jq -r '[.[].id] | join(",")' > channels.txt
  • Inspect the output yourself before trusting any example, including this one. Field names are a contract you should read, not assume.
  • Keep channel IDs in a file your scripts read, not in your shell history where they get lost the next time you clear it.
  • Fail loudly. A script that reads a missing field should exit non-zero, not quietly schedule an empty post to thirty channels.
  • Keep POSTQUEEN_API_KEY in the environment or a secret manager, never in the repository that holds your posts.

Scripting a week

The payoff is a queue you can regenerate. Keep next week's posts as files, one per post, and let a script turn them into a schedule. The pattern below reads a directory, assigns each file a slot on consecutive mornings, and creates the post. Every flag in it is one you already saw above.

terminal
#!/usr/bin/env bash
set -euo pipefail
 
CHANNELS=$(cat channels.txt)
 
# One post per file, consecutive mornings,
# starting tomorrow. GNU date shown here;
# on macOS use: date -u -v+1d
day=1
for file in ./queue/*.txt; do
when=$(date -u -d "+${day} day" +%Y-%m-%dT09:00:00Z)
postqueen posts:create \
-c "$(cat "$file")" \
-s "$when" \
-i "$CHANNELS"
day=$((day + 1))
done
 
# Receipts
postqueen posts:list

Thirty lines of bash and next week is a directory. The real gain is not the typing you saved, it is that the queue became reviewable: a colleague can read the diff, catch the sentence that reads badly, and approve the branch. Nothing about that workflow is new to anyone on your team, which is precisely why it survives contact with a busy week.

Cron patterns that will not surprise you

One mistake is worth calling out before you write any cron at all: do not use cron to publish. The scheduler already publishes. Use cron to fill the queue ahead of time and let the scheduler own the clock. A cron job that posts right now is a job that posts during an outage, posts a launch that got delayed by a day, and posts at 4am the weekend the clocks change.

Do not cron the publish. Cron the queue, and let the scheduler own the clock.
  • Run the fill job weekly and schedule posts several days out, so there is a review window between the machine deciding and the audience seeing.
  • Cron runs in the server's local time and your timestamps are UTC. Pick one, convert deliberately, and expect the two to disagree twice a year.
  • Wrap the job in flock so a slow run never overlaps a fast one and files the same week twice.
  • Make it safe to re-run. Track which files you already queued, or a retry becomes a duplicate in front of an audience.
  • Log somewhere you will actually read, and exit non-zero on failure so your monitoring has something to notice.
terminal
# Fill next week every Monday at 8 AM,
# never overlapping with itself
0 8 * * 1 /usr/bin/flock -n /tmp/pq.lock \
/home/deploy/fill-queue.sh >> /var/log/queue.log 2>&1

Guardrails before you automate

Two habits keep this pleasant. First, schedule instead of publishing while you are still building. A post queued for tomorrow morning can be edited or deleted from the calendar; a post that already went out to five networks cannot be recalled from any of them, and the screenshot is forever. Second, keep the key narrow and revocable. It is one string in one environment variable, and revoking it stops every script and every agent at once, which is exactly the property you want the day a laptop goes missing.

postqueen is open source under AGPL-3.0, so if you would rather the whole thing run on hardware you control, the same CLI talks to a self-hosted install by pointing POSTQUEEN_API_URL at your own backend. Cloud or self-hosted, the commands do not change. That is the part that makes the scripts worth writing: they outlive the decision about where the thing runs.

Ready to get started?

Queue this week's posts in minutes, or hand the whole thing to your favorite AI. postqueen keeps publishing either way.

Seven days free. Cancel in one click from settings.