PostNitro CLI
The PostNitro CLI creates on-brand social media posts — multi-slide carousels, single images, and short videos — and schedules them to LinkedIn, Instagram, TikTok, and Threads, all from the command line. It’s a thin, scriptable wrapper over the Embed API, built for AI agents, automations, and scripts: every command takes flags or JSON in and prints JSON out (clean stdout on success, JSON error on stderr) — no colors, tables, or interactive prompts to parse around. It uses the same Embed API key and credits as the REST API and MCP server.
Quick Reference
| Package | @postnitro/cli (npm) |
| Binary | postnitro |
| Requires | Node.js ≥ 18, and a PostNitro account on a paid plan |
| Authentication | --api-key, POSTNITRO_API_KEY, or a saved key — keys start with pn- |
| API key | Same key as the Embed API — how to get one |
| Output | JSON to stdout on success (exit 0); JSON error to stderr (exit 1) |
| GitHub | postnitro/postnitro-agent |
Installation
# Install globally from npm (recommended)
npm install -g @postnitro/cli
postnitro --help
# Or run without installing
npx @postnitro/cli --helpInstall as a skill
You can also install PostNitro as a skill for your AI coding agent — it teaches the agent to drive the CLI on your behalf:
npx skills add postnitro/postnitro-agentFor Claude Code specifically, you can instead add it as a plugin:
# in Claude Code
/plugin marketplace add postnitro/postnitro-agent
/plugin install postnitro@postnitro-agentThe skill is defined in SKILL.md at the repo root (with a copy under skills/postnitro/); the Claude Code plugin manifests live in .claude-plugin/.
Authentication
Get an API key from PostNitro → Profile → Embed → Generate API Key (see Obtaining an API Key). Provide it in any of these ways (highest precedence first):
--api-key <key>on any commandPOSTNITRO_API_KEYenvironment variable- Saved config —
postnitro auth set-key <key>(stored at~/.postnitro-cli/config.json)
postnitro auth set-key pn-xxxxxxxxxxxx # save it once
postnitro auth status # check what's configured (key is masked)
postnitro auth clear # remove the saved keySecurity:
auth set-keystores your key in plaintext at~/.postnitro-cli/config.json. Restrict its permissions, avoid shared machines, and use--api-keyorPOSTNITRO_API_KEYin CI.
Core concepts
Post type × content source. Creating a post is two independent choices:
generate (AI writes it) | import (you supply content) | |
|---|---|---|
| carousel (multi-slide) | postnitro carousel generate | postnitro carousel import (slides array) |
| image (single) | postnitro image generate | postnitro image import (single slide object) |
Asynchronous by default. Creating a post kicks off a background job and returns an embedPostId. Add --wait to poll to completion and get the final output in one call, or poll manually with status / output.
embedPostId vs designId. Creation returns an embedPostId (the job). To schedule a post you need its designId (from the --wait result or output). Never pass an embedPostId to schedule — see carousel identifiers.
Editor link. Every completed post’s output includes an editorUrl — a deep link to open the design in the PostNitro editor.
JSON in / JSON out. Complex inputs can be passed inline as JSON (agent-friendly) or from a file; inline always wins. Every command prints JSON to stdout on success (exit 0) or a JSON error to stderr (exit 1).
Smart defaults. --template-id / --brand-id / --preset-id resolve in this order: explicit flag → saved default (defaults set) → auto-select when your workspace has exactly one candidate.
Global options
Available on every command:
| Option | Description |
|---|---|
--api-key <key> | PostNitro API key (falls back to POSTNITRO_API_KEY, then saved config) |
-V, --version | Print the CLI version |
-h, --help | Show help for any command or subcommand |
Command reference
auth
Manage the saved PostNitro API key.
| Command | Description |
|---|---|
auth set-key <apiKey> | Save an API key to ~/.postnitro-cli/config.json |
auth status | Show whether a key is configured (masked) and where it’s coming from |
auth clear | Remove the saved API key |
defaults
Save default templateId / brandId / presetId / responseType so create commands don’t need them every time.
| Command | Options | Description |
|---|---|---|
defaults get | — | Show saved defaults for the active API key |
defaults set | --template-id <id> --brand-id <id> --preset-id <id> --response-type <PDF|PNG|DESIGN> | Save one or more defaults (at least one required) |
postnitro defaults set --template-id tpl_123 --brand-id brd_456 --preset-id prs_789 --response-type PDF
postnitro defaults gettemplate
Browse available carousel templates.
| Command | Options | Description |
|---|---|---|
template list | --page <n> (default 1) · --limit <n> (default 10, max 50) | List templates with IDs, names, and dimensions |
postnitro template list --limit 20brand
Manage brand kits (logo, name, handle stamped on designs). See the Brands API for full field definitions.
| Command | Description |
|---|---|
brand list [--page <n>] [--limit <n>] | List brand kits |
brand get <id> | Fetch a single brand kit |
brand create [options] | Create a brand kit (required: --name, --handle, --image, or --data/--file) |
brand update <id> [options] | Update a brand kit (all fields required by the API — fetch current values first) |
Options for create / update:
| Option | Description |
|---|---|
--name <name> | Brand display name |
--handle <handle> | Social handle, e.g. @postnitroai |
--image <url> | Logo image URL |
--company-detail | Treat as a company brand (vs personal) |
--data <json> | Full brand object as inline JSON (overrides --file and the flags) |
--file <path> | Full brand object from a JSON file (overridden by --data) |
--no-show-name / --no-show-handle / --no-show-image | Hide that element on slides |
postnitro brand create --name "PostNitro" --handle "@postnitroai" --image "https://.../logo.png" --company-detail
postnitro brand create --data '{"name":"PostNitro","handle":"@postnitroai","image":"https://.../logo.png","isCompanyDetail":true}'preset
Browse available AI generation presets (each bundles social platform, tone, audience, language, slide count, and model).
| Command | Options | Description |
|---|---|---|
preset list | --page <n> · --limit <n> (max 50) | List AI presets with IDs |
social
Manage connected social accounts. See the Social Accounts API for full field definitions.
| Command | Description |
|---|---|
social list | List connected accounts, grouped by platform (returns the IDs used for --selected-accounts) |
social get <id> | Fetch a single account, including usage stats |
social disconnect <id> --yes | Disconnect an account. Destructive, requires --yes, cannot be undone |
carousel
Generate, import, and inspect multi-slide carousel posts.
| Command | Description |
|---|---|
carousel import-template | Print the exact slide structure and rules for carousel import |
carousel generate [options] | Generate a carousel with AI |
carousel import [options] | Create a carousel from your own slides |
carousel status <embedPostId> | Check generation status + processing logs |
carousel output <embedPostId> | Retrieve the final output (files, designId, editorUrl) |
carousel generate options:
| Option | Description |
|---|---|
--context <text> | Required. Topic/prompt, or an article/X URL (depending on --type) |
--type <text|article|x> | How --context is interpreted (default text) |
--instructions <text> | Extra guidance for the AI |
--template-id <id> / --brand-id <id> / --preset-id <id> | Override saved defaults |
--response-type <PDF|PNG|DESIGN> | Output format (default PDF) — see Response types |
--requestor-id <id> | Optional custom tracking ID |
--wait | Poll until complete and print the final output |
--generate-images + --image-context + --image-placement + --image-strategy | AI image generation |
carousel import options: same as above except no --type / --instructions / --preset-id, plus:
| Option | Description |
|---|---|
--slides <json> | Slides as inline JSON — a bare array or {"slides":[...]} (overrides --file) |
--file <path> | Path to a JSON file containing the slides array |
# AI-generated
postnitro carousel generate --context "5 tips for remote work" --type text --wait
postnitro carousel generate --context "https://example.com/post" --type article --wait
# Import your own slides
postnitro carousel import --slides '{"slides":[
{"type":"starting_slide","heading":"Your Title","description":"Intro"},
{"type":"body_slide","heading":"Key Point","description":"Details"},
{"type":"ending_slide","heading":"Take Action!","cta_button":"Learn More"}
]}' --waitCarousel slide rules: the array must contain exactly 1 starting_slide (first), ≥1 body_slide, and exactly 1 ending_slide (last). Every slide needs a heading. Optional per slide: sub_heading, description, image, background_image, cta_button, and layoutType/layoutConfig (see Infographic layout). Run carousel import-template for the authoritative schema.
image
Generate, import, and inspect single-image posts. Mirrors carousel, but produces one image and import takes a single slide object (not an array).
| Command | Description |
|---|---|
image import-template | Print the exact slide object and rules for image import |
image generate [options] | Generate a single image with AI (same options as carousel generate) |
image import [options] | Create an image from your own content |
image status <embedPostId> | Check generation status + logs |
image output <embedPostId> | Retrieve the final output |
image import options: same as carousel import, but slide input is a single object:
| Option | Description |
|---|---|
--slide <json> | The slide as inline JSON — a single object (overrides --file) |
--file <path> | Path to a JSON file with a single slide object (or { "slides": {...} }) |
postnitro image generate --context "Announce our new scheduling feature" --wait
postnitro image import --slide '{"heading":"Welcome!","sub_heading":"Subtitle","cta_button":"Learn more"}' --waitImage slide fields (single object; heading required, all others optional): heading, sub_heading, description, cta_button, image, background_image, plus layoutType/layoutConfig for infographics. Any other field is rejected. Sending an array is rejected — arrays are carousel-only.
video
Generate, import, and inspect video posts. Slides are scenes, so video import takes the same slide array as carousel import — see Video posts for the API-level rules.
| Command | Description |
|---|---|
video import-template | Print the scene rules and render settings for video import |
video generate [options] | Generate a video with AI (each AI-written slide becomes a scene) |
video import [options] | Create a video from your own scenes |
video status <embedPostId> | Check generation status + logs |
video output <embedPostId> | Retrieve the final output (MP4 URL, designId, editorUrl) |
Video-only options (on top of the carousel options):
| Option | Description |
|---|---|
--response-type <MP4|DESIGN> | A video accepts nothing else — PDF/PNG are rejected. Default DESIGN |
--video-duration <seconds> | The whole video’s length, not per scene. At least 5, under 60. Required with --response-type MP4 |
--audio-id <id> | Audio track ID from audio list — an ID, never a URL. Omit for a silent video |
# AI-generated, rendered to MP4
postnitro video generate --context "3 habits that make remote teams faster" \
--response-type MP4 --video-duration 30 --wait
# Your own scenes, with an audio track
AUDIO=$(postnitro audio list | jq -r '.audios[0].id')
postnitro video import --file ./scenes.json \
--response-type MP4 --video-duration 30 --audio-id "$AUDIO" --wait
# Design only — no render; finish it in the video maker via editorUrl
postnitro video generate --context "..." --waitRendering a video takes longer than a carousel — typically 15–45s with --wait and MP4, and longer for designs with animations or GIFs (which use the enhanced renderer). A saved PDF/PNG default doesn’t apply to a video: it’s treated as DESIGN and noted in warnings rather than failing the call. The duration and audio are reused automatically when the video is scheduled as a reel.
audio
List and delete the workspace’s audio tracks — the source of the --audio-id used by video, and of postSettings.audioId when scheduling a reel. See the Audio API.
| Command | Description |
|---|---|
audio list [--page <n>] [--limit <n>] | List audio tracks with their IDs |
audio delete <id> --yes | Delete a track and its stored file. Destructive, requires --yes |
postnitro audio list
postnitro audio delete aud_123 --yesaudio list returns { id, name, url, duration, artistName, source, createdAt } per track. Pass id as --audio-id; url is for previewing only. A track’s duration is independent of --video-duration — a longer track is cut off at the video’s length.
Uploading is done in the PostNitro app. The CLI (like the API) lists and deletes audio but cannot upload it. An empty list comes back with a
notesaying so — create the video without--audio-idin the meantime.
audio delete is refused while a scheduled post still references the track. Videos already rendered to MP4 keep their audio, since the track is baked into the file.
schedule
Manage scheduled posts and drafts. Full CRUD is also available via the Schedule API.
| Command | Description |
|---|---|
schedule list --from <date> --to <date> [--accounts <id,id>] | List scheduled posts/drafts in a date range, optionally limited to specific accounts |
schedule get <id> | Fetch a single scheduled post |
schedule create [options] | Create a scheduled post or draft |
schedule update <id> [options] | Update a post — REPLACES state, send the full intended body |
schedule delete <id> --yes | Delete a scheduled post/draft. Destructive, requires --yes |
schedule create / update options:
| Option | Description |
|---|---|
--status <DRAFT|SCHEDULED> | Required. SCHEDULED publishes at the given time; DRAFT saves without publishing |
--scheduled-at <iso> | Required. ISO-8601 datetime, must be ≥ 5 minutes in the future (trailing Z) |
--design-id <id> | The design to attach (from output’s designId — not the embedPostId) |
--post-content <json> | Captions keyed by platform: common, linkedin, instagram, tiktok, facebook, threads |
--selected-accounts <json> | Array of social-account IDs |
--linkedin-post-settings / --instagram-post-settings / --tiktok-post-settings / --threads-post-settings <json> | Per-platform settings — see Platform settings |
--post-settings <json> | Reel video settings, e.g. {"videoDuration":30,"audioId":"aud_123"}. Optional — see below |
--file <path> | JSON file with any of the above (inline flags override it) |
A post must have either --design-id or non-empty --post-content. Hashtags are auto-extracted from captions.
--post-settings may be omitted for a reel: the API fills the duration and audio from the settings the attached design was generated with, then falls back to 30 seconds with no audio. videoDuration must be at least 5 and under 60, and audioId must be an audio ID in your workspace.
schedule list accepts --accounts <id,id> (comma-separated IDs from social list) to narrow the range to specific accounts. It filters posts, not the accounts within them: a post targeting LinkedIn and Instagram is returned when you filter by either, and it still reports both. Unknown IDs match nothing rather than erroring.
postnitro schedule create \
--status SCHEDULED \
--scheduled-at "2026-12-31T13:00:00Z" \
--design-id dsg_abc \
--selected-accounts '["acct_123"]' \
--linkedin-post-settings '{"postType":"document","postTitle":"5 remote work tips"}' \
--post-content '{"common":"New carousel 🚀 #remotework"}'
postnitro schedule list --from "2026-01-01" --to "2026-12-31"
postnitro schedule list --from "2026-01-01" --to "2026-12-31" --accounts "acct_123,acct_456"
postnitro schedule delete sch_123 --yesgenerate-and-schedule
One-shot: generate with AI → wait → schedule in a single call. May take 30–180s.
Takes every generate flag (--context required, --type, --instructions, --preset-id, …), plus --post-type CAROUSEL|IMAGE|VIDEO (default CAROUSEL; a video also takes --video-duration/--audio-id), the AI-image flags, and all the schedule create flags (--status and --scheduled-at required). --file here is the schedule body.
If generation succeeds but scheduling fails, the error returns the designId so you can retry schedule create without regenerating (and re-spending credits).
postnitro generate-and-schedule \
--context "How AI agents automate content" --type text \
--status SCHEDULED --scheduled-at "2026-12-31T12:00:00Z" \
--selected-accounts '["acct_123"]' \
--linkedin-post-settings '{"postType":"document","postTitle":"How AI agents automate content"}' \
--post-content '{"common":"New drop 🚀 #ai #automation"}'import-and-schedule
One-shot: import your own content → wait → schedule in a single call. The import-side counterpart of generate-and-schedule.
| Option | Description |
|---|---|
--post-type <CAROUSEL|IMAGE|VIDEO> | Post kind (default CAROUSEL) |
--slides <json> | CAROUSEL/VIDEO slides as inline JSON (array or {"slides":[...]}) |
--slide <json> | IMAGE slide as inline JSON (single object) |
--slides-file <path> | Slides from a file (array for CAROUSEL/VIDEO, object for IMAGE) |
--video-duration <seconds> / --audio-id <id> | VIDEO only — see video |
--template-id / --brand-id / --response-type / --requestor-id | As in import |
--status / --scheduled-at | Required (as in schedule create) |
--design-id · --file · --post-content · --selected-accounts · --*-post-settings · --post-settings | Scheduling body (as in schedule create) |
| AI-image flags | --generate-images, --image-context, --image-placement, --image-strategy |
Flag note: here
--fileis the schedule body (likegenerate-and-schedule), so slide content comes from--slides/--slide/--slides-file, not--file.
postnitro import-and-schedule \
--slides '{"slides":[ ... ]}' \
--status SCHEDULED --scheduled-at "2026-12-31T12:00:00Z" \
--selected-accounts '["acct_123"]' \
--post-content '{"common":"..."}'AI image generation
Opt-in: have AI generate images and bake them into the design before rendering. Available on all six create commands and both one-shot commands — carousels, images, and videos alike.
| Flag | Values | Default | Notes |
|---|---|---|---|
--generate-images | (boolean) | off | Opt in. Also implied by any flag below. |
--image-context <text> | string | — | Required when generating images: a short visual brief for the prompts |
--image-placement <mode> | auto | background | in-line | auto | auto = AI decides per slide |
--image-strategy <mode> | strategic | all | strategic | strategic ≈ 50% of slides; all = every eligible slide |
postnitro carousel generate --context "How scheduling saves marketers time" \
--generate-images --image-context "upbeat and professional, product-focused" \
--image-placement auto --image-strategy all --wait- Best-effort. The post still completes if image generation fails or isn’t permitted. With
--wait, the result carries animageGenerationfield (theGENERATE_IMAGESstep); aFAILEDstatus there explains why (e.g. free plan can’t generate AI images, or the org is over its AI-image quota). Without--wait, the same step appears instatuslogs. - Credits. AI images consume the organization’s separate AI-image quota — the post’s slide-based credits are unchanged.
- Adds latency (real images are rendered).
Infographic layout
On either import command, set layoutType: "infographic" on a slide (with a layoutConfig) to render data columns (max 3) instead of an image. Works on both carousel slides and the single image slide.
layoutConfig fields (omitted fields use the defaults shown):
| Field | Type | Default | Notes |
|---|---|---|---|
hasHeader | boolean | true | Show a header |
columnCount | number | 1 | 1–3 |
displayCounterAs | string | "counter" | "counter" or "none" |
columnDisplay | string | "grid" | "grid" (comparative) or "cycle" (sequential — put all data in the first column) |
columnData | array | [] | The columns |
Each columnData entry: id (string), header (string), content (array). Each content item: id (string), icon (string | null), title (string), description (HTML string, e.g. <p dir="ltr">…</p>), titleEnabled (boolean), descriptionEnabled (boolean).
Important: the
idfields on columns and items are caller-provided and required — the API stores them as-is and does not auto-generate them. IflayoutTypeisinfographicbutlayoutConfigis missing, the slide falls back to the default layout.
{
"heading": "Our 2026 Results",
"layoutType": "infographic",
"layoutConfig": {
"hasHeader": true,
"columnCount": 3,
"columnDisplay": "grid",
"displayCounterAs": "counter",
"columnData": [
{ "id": "col-1", "header": "Growth", "content": [
{ "id": "item-1", "icon": null, "title": "+42%", "description": "<p dir=\"ltr\">Revenue YoY</p>", "titleEnabled": true, "descriptionEnabled": true }
]}
]
}
}Platform settings
Pass per-platform behavior via the --*-post-settings flags when scheduling. Settings are conditionally required based on the platforms among your --selected-accounts. See Platform settings for the full reference.
| Flag | Shape |
|---|---|
--linkedin-post-settings | {"postType":"carousel|document|image|reel","postTitle":"..."} — document needs a 5–90 char postTitle |
--instagram-post-settings | {"postType":"carousel|image|reel","postAsStory":false} |
--tiktok-post-settings | {"postType":"carousel|reel","privacyLevel":"PUBLIC_TO_EVERYONE|MUTUAL_FOLLOW_FRIENDS|SELF_ONLY","canComment":true,"canDuet":true,"canStitch":true,"autoAddMusic":false,"postTitle":null,"isBrandedContent":false,"isYourBrand":false,"isThirdPartyBrand":false,"isAIGeneratedContent":true} |
--threads-post-settings | {"postType":"carousel|image|reel"} |
--post-settings (reel) | {"videoDuration":30,"audioId":"..."} |
LinkedIn tip: PDF carousels are normally posted as
postType: "document"(which needs apostTitle).
Response types & output
--response-type accepts four values (CLI default is PDF, except on video, which defaults to DESIGN):
| Value | Behavior |
|---|---|
PDF | Renders and returns a PDF (single file URL in data) |
PNG | Renders and returns PNG image(s) (one URL per slide in data) |
MP4 | Renders and returns a video (single file URL in data). video only |
DESIGN | Skips rendering. Creates the editable design only — no file. Fastest/lightest when you only need to schedule or edit |
MP4 and the other rendered formats don’t mix: a video accepts only MP4 or DESIGN, and MP4 is rejected for carousels and images. MP4 also can’t be stored with defaults set, since it would break every carousel and image call — pass it per call.
Every completed output includes designId, name, size, and editorUrl. PDF/PNG/MP4 additionally include type, mimeType, and data (the file URLs); DESIGN omits those three.
// PNG output (excerpt)
{
"designId": "dsg_abc",
"name": "5 remote work tips",
"editorUrl": "https://postnitro.ai/app/carousel-maker/pn-xyz/dsg_abc",
"type": "png",
"mimeType": "image/png",
"data": ["https://.../slide_0.png", "https://.../slide_1.png"]
}Environment variables
| Variable | Required | Default | Description |
|---|---|---|---|
POSTNITRO_API_KEY | No* | — | Your PostNitro Embed API key |
POSTNITRO_CONFIG_DIR | No | ~/.postnitro-cli | Where the saved key + defaults are stored |
* Either --api-key, POSTNITRO_API_KEY, or a saved key (auth set-key) is required.
Errors & exit codes
Every command prints JSON. Failures go to stderr and exit non-zero:
{ "success": false, "error": { "message": "PostNitro API error (422): ...", "statusCode": 422 } }- Exit 0 — success (JSON on stdout)
- Exit 1 — error (JSON on stderr)
| Common error | Fix |
|---|---|
No API key found | Pass --api-key, set POSTNITRO_API_KEY, or run auth set-key |
Missing --brand-id ... multiple candidates | Pass the ID or save one via defaults set |
Scheduled at is in the past | Use a future ISO-8601 datetime (≥ 5 min ahead, trailing Z) |
Slides must be an array with at least 3 entries | Provide starting + body + ending slides |
An IMAGE post takes a single slide object, not an array | Use --slide (object) for images, --slides (array) for carousels |
AI image generation requires --image-context | Add --image-context "<brief>" when using --generate-images |
Refusing to delete ... without --yes | Add --yes to confirm destructive actions |
Credits & pricing
The CLI consumes the same credits as the Embed API:
- Content import: ~1 credit per slide
- AI generation: ~2 credits per slide
- AI images: consume the organization’s separate AI-image quota (not post credits); unavailable on the free plan
- Response type (
PDF/PNG/DESIGN) does not change credit cost
Command cheat sheet
# Auth
postnitro auth set-key <key> | status | clear
# Discovery + defaults
postnitro template list | brand list | preset list | social list
postnitro defaults set --template-id <id> --brand-id <id> --preset-id <id> --response-type PDF
# Create (carousel, image, or video; async — use --wait; result has designId + editorUrl)
# --response-type PDF|PNG|DESIGN (MP4 for video) | optional AI images: --generate-images --image-context "brief" [--image-placement …] [--image-strategy …]
postnitro carousel generate --context "topic|url" --type text|article|x [--instructions "…"] --wait
postnitro carousel import (--slides '{"slides":[…]}' | --file ./slides.json) --wait
postnitro image generate --context "topic|url" --type text|article|x --wait
postnitro image import (--slide '{"heading":"…"}' | --file ./slide.json) --wait
postnitro video generate --context "topic|url" --response-type MP4 --video-duration 30 [--audio-id <id>] --wait
postnitro video import (--slides '{"slides":[…]}' | --file ./scenes.json) --response-type MP4 --video-duration 30 --wait
postnitro carousel status <embedPostId> | carousel output <embedPostId> # (also: image | video status | output)
# Audio for videos & reels (upload happens in the app)
postnitro audio list | audio delete <audioId> --yes
# Brand kits
postnitro brand create (--name --handle --image [--company-detail] | --data '{…}')
postnitro brand update <id> …
# Schedule (use designId, not embedPostId; --scheduled-at ≥ 5 min in the future)
postnitro schedule create --status SCHEDULED|DRAFT --scheduled-at "<iso>" --design-id <id> \
--selected-accounts '["<id>"]' --linkedin-post-settings '{"postType":"document","postTitle":"…"}' \
--post-content '{"common":"caption"}'
postnitro schedule list --from "<date>" --to "<date>" [--accounts "<id>,<id>"] | get <id> | update <id> … | delete <id> --yes
# Social accounts
postnitro social list | get <id> | disconnect <id> --yes
# One-shot: create + schedule (both take --post-type CAROUSEL|IMAGE|VIDEO + the AI-image flags)
postnitro generate-and-schedule --context "topic" --status SCHEDULED --scheduled-at "<iso>" …
postnitro import-and-schedule --slides '{"slides":[…]}' --status SCHEDULED --scheduled-at "<iso>" … # or --slide for image
# Help
postnitro --help | postnitro <command> --help | postnitro <command> <subcommand> --helpCLI vs. MCP vs. Embed API vs. Embed SDK
| Best for | |
|---|---|
| CLI | Terminal workflows, shell scripts, CI pipelines, and AI agents that shell out — JSON in, JSON out |
| MCP Server | AI assistants and agents creating and scheduling posts conversationally (Claude, Cursor, custom agents) |
| Embed API | Programmatic automation — Make.com, Zapier, n8n, cron jobs, custom backends |
| Embed SDK | Letting your users visually create and edit carousels inside your web app |
Support
- Email: support@postnitro.ai
- Live Chat: Available on postnitro.ai
- npm:
@postnitro/cli - GitHub: postnitro/postnitro-agent