Search

Search the docs…

Build

CLI

Schedule posts from your terminal, shell scripts, cron jobs and CI pipelines. One command, the same rules as the app.

Install

Node.js 18 or newer. No other dependencies. Run it once with npx or install it globally:

npx postika --help

# or
npm install -g postika
postika --version

Log in

  1. 1
    In Postika, open your project → Connect AI (Conectar IA) → Project keys (Claves de proyecto) and create a key (ptk_…).
  2. 2
    Run postika login and paste it. The key is checked against the server and saved to ~/.config/postika/config.json, readable only by you (0600).
postika login
postika whoami

In CI, skip login and set the key as a secret environment variable instead. --api-key and --base-url work on every command too.

VariableUse
POSTIKA_API_KEYAPI key. Takes priority over the saved one.
POSTIKA_BASE_URLServer URL, for a self-hosted or test instance. Defaults to https://postika.app.
NO_COLORPlain output without colors.

Commands

CommandWhat it does
postika loginSave an API key
postika logoutRemove the saved key
postika whoamiProject, time zone, plan, role and warnings of the current key
postika projectsProjects the key can reach
postika channelsConnected channels with their IDs and limits
postika posts listPosts of the next 14 days, a date range or a status
postika posts createSchedule, publish now, send for approval or save a draft
postika posts get <id>One post with the status, error and URL of each channel
postika posts delete <id>Delete a post (asks for confirmation; --yes to skip)
postika posts approve <id>Approve a post pending approval

Add --json to any command to print the raw API response, ready for jq. Errors go to stderr with a non-zero exit code; with --json they are printed as JSON too.

Create a post

# Schedule (project local time)
postika posts create --text "We just shipped dark mode" --channels linkedin,x --at "2026-11-12 09:30"

# Photo from your disk, saved as a draft
postika posts create --text "Behind the scenes" --channels @mybrand --media ./photo.jpg --draft

# Every channel, pending approval, shorter text for X
postika posts create -t "Our autumn collection is live" -c all \
  --text-for "x=Autumn drop is live 🍂" --at "2026-11-14 18:00" --approval

# Text from a file or another command
cat post.txt | postika posts create --text - --channels threads --now
Options
--text, -tstringrequired
Post text, 1 to 5000 characters. - reads it from stdin.
--channels, -clistrequired
Comma-separated channel IDs, handles (@mybrand) or network names (linkedin, x, instagram…), or all. A handle matches every channel with that handle.
--atstring
YYYY-MM-DD HH:MM in the project's time zone. Required to schedule or send for approval.
--media, -mfile | url
A local photo or video (uploaded with POST /api/v1/media) or a public https:// link. Repeat it or separate with commas, up to 10.
--draftflag
Save as a draft (--at optional).
--approvalflag
Leave it pending until an owner or admin approves it.
--nowflag
Publish right away.
--text-forstring
Different text for one channel: "<channel>=<text>". Repeatable.
--notestring
Note for whoever approves it. Not published.

Without --draft, --approval or --now, the post is scheduled for --at. The same checks as the app run first: character limits, required media, channels to reconnect and the plan.

List and inspect posts

postika posts list                                  # next 14 days
postika posts list --from 2026-12-01 --to 2026-12-31   # up to 62 days
postika posts list --status failed                  # latest 100 failed posts
postika posts get f2b1c0de-5a4e-4d0b-8a77-0c6e3b9d1a42
postika posts delete f2b1c0de-5a4e-4d0b-8a77-0c6e3b9d1a42 --yes

Scripts and CI

GitHub Actions

Announce every release on your channels. Store the key as a repository secret.

.github/workflows/announce.yml
on:
  release:
    types: [published]

jobs:
  announce:
    runs-on: ubuntu-latest
    steps:
      - run: |
          npx -y postika posts create \
            --text "${{ github.event.release.name }} is out: ${{ github.event.release.html_url }}" \
            --channels linkedin,x --approval \
            --at "$(TZ=Europe/Madrid date -d '+1 hour' '+%Y-%m-%d %H:%M')"
        env:
          POSTIKA_API_KEY: ${{ secrets.POSTIKA_API_KEY }}

With jq

# IDs of every failed post
postika posts list --status failed --json | jq -r '.[].id'

# Channel ID of your LinkedIn page
postika channels --json | jq -r '.[] | select(.network == "LinkedIn") | .id'
Self-hosting or testing?
Point the CLI at another server with --base-url http://localhost:3000 or POSTIKA_BASE_URL. Errors and limits are the same as the REST API; see Errors & limits.