{"id":"d1b0376b-718e-40e4-98b8-92f290e7648d","entityType":"agent","slug":"clawhub-iammuneeb-postnitro","name":"PostNitro","canonicalUrl":"https://www.xpersona.co/agent/clawhub-iammuneeb-postnitro","canonicalPath":"/agent/clawhub-iammuneeb-postnitro","generatedAt":"2026-10-12T12:40:28.425Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T23:35:32.750Z","emptyReason":null},"description":"Create on-brand social media carousels, single-image posts, and short videos, and schedule them to LinkedIn, Instagram, TikTok, and Threads from a single command. Turn a topic, article, or X thread into a finished multi-slide post, image, or video (with an optional audio track) — or import your own","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 975 downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s17fhdpk451rztcqhmqcbkjwas885q1k:postnitro","sourceUrl":"https://clawhub.ai/iammuneeb/postnitro","homepage":"https://clawhub.ai/iammuneeb/skills/postnitro","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/iammuneeb/postnitro","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/iammuneeb/skills/postnitro","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"PostNitro technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T23:35:32.750Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T23:35:32.750Z","emptyReason":null},"stars":null,"forks":null,"downloads":975,"likes":null,"task":null,"library":null,"packageName":null,"latestVersion":"1.3.0","tractionLabel":"975 downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T23:35:32.734Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T23:35:32.750Z","lastCrawledAt":"2026-10-11T23:35:32.734Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T23:35:32.734Z","lastVerifiedAt":null,"highlights":[{"version":"1.3.0","createdAt":"2026-08-18T22:11:09.440Z","changelog":"**PostNitro 1.3.0 adds video creation and import.** - Added support for short video creation: generate or import slides as video scenes, with optional audio and MP4 output. - Introduced the `video generate` and `video import` commands. - Clarified output options: videos support `MP4` (single file) or `DESIGN` modes only. - Updated documentation to reflect video features and new CLI usage examples. - Added a video import example file. - Removed the old skill card markdown file.","fileCount":9,"zipByteSize":20616},{"version":"1.2.1","createdAt":"2026-07-17T11:56:57.494Z","changelog":"Adds opt-in AI image generation (the Embed API's `generateImages` feature) and fixes the API base URL to the hosted endpoint. ### Added - **AI image generation** (opt-in) on all generate/import commands and both one-shot commands: `--generate-images`, `--image-context <text>` (**required** when generating images), `--image-placement auto|background|in-line`, `--image-strategy strategic|all`. Best-effort — `--wait` results surface the `GENERATE_IMAGES` job step as `imageGeneration` (a COMPLETED post can still have a skipped/failed image step, e.g. free plan / over AI-image quota). AI images bill against the org's separate AI-image quota, not the post's slide credits. - `import-and-schedule` — one-shot import + schedule, the counterpart to `generate-and-schedule`. Takes `--slides` (carousel array) / `--slide` (single image) / `--slides-file`, plus `--post-type CAROUSEL|IMAGE`, the schedule options, and the AI-image flags. `--file` is the schedule body (as in `generate-and-schedule`). On scheduling failure it returns the `designId` so you can retry without re-importing. ### Removed - The `--base-url` global flag and `POSTNITRO_API_BASE_URL` environment variable. The API base URL is now a fixed constant (`https://embed-api.postnitro.ai`) — PostNitro is hosted, not self-hosted, so the endpoint is always the same.","fileCount":8,"zipByteSize":16493},{"version":"1.2.0","createdAt":"2026-07-17T11:47:27.838Z","changelog":"Tracks the Embed API changes (IMAGE posts, `DESIGN` response type, `editorUrl`, infographic layout on images). ### Added - `image generate | import | status | output | import-template` — single-image posts, mirroring the `carousel` commands. `image import` takes a **single slide object** (via `--slide`/`--file`), not an array, and supports the infographic layout (`layoutType`/`layoutConfig`). - `DESIGN` as a `--response-type` value — creates the editable design without rendering a PDF/PNG (returns `designId` + `editorUrl` only). Accepted anywhere `--response-type` is (generate/import, `image`, `generate-and-schedule`, `defaults set`). - `editorUrl` (deep link to open the design in the editor) surfaced in all generate/import/output results. - `--post-type CAROUSEL|IMAGE` on `generate-and-schedule`. ### Changed - `--response-type` values are now validated/normalized (case-insensitive) to `PDF`/`PNG`/`DESIGN`; invalid values fail fast with a clear error. - The CLI still defaults `--response-type` to `PDF` and always sends it explicitly, so it is unaffected by the API's new `DESIGN` default for omitted values. - `carousel output` now reports `aspectRatio`/`editorUrl` and omits `data`/`mimeType`/`outputType` for `DESIGN` responses.","fileCount":8,"zipByteSize":16501},{"version":"1.1.1","createdAt":"2026-07-17T11:45:54.847Z","changelog":"Tracks the Embed API changes (IMAGE posts, `DESIGN` response type, `editorUrl`, infographic layout on images). ### Added - `image generate | import | status | output | import-template` — single-image posts, mirroring the `carousel` commands. `image import` takes a **single slide object** (via `--slide`/`--file`), not an array, and supports the infographic layout (`layoutType`/`layoutConfig`). - `DESIGN` as a `--response-type` value — creates the editable design without rendering a PDF/PNG (returns `designId` + `editorUrl` only). Accepted anywhere `--response-type` is (generate/import, `image`, `generate-and-schedule`, `defaults set`). - `editorUrl` (deep link to open the design in the editor) surfaced in all generate/import/output results. - `--post-type CAROUSEL|IMAGE` on `generate-and-schedule`. ### Changed - `--response-type` values are now validated/normalized (case-insensitive) to `PDF`/`PNG`/`DESIGN`; invalid values fail fast with a clear error. - The CLI still defaults `--response-type` to `PDF` and always sends it explicitly, so it is unaffected by the API's new `DESIGN` default for omitted values. - `carousel output` now reports `aspectRatio`/`editorUrl` and omits `data`/`mimeType`/`outputType` for `DESIGN` responses.","fileCount":8,"zipByteSize":16405},{"version":"1.1.0","createdAt":"2026-07-13T15:34:49.243Z","changelog":"- Added support for single-image social posts via `image` commands, alongside multi-slide carousels. - Updated documentation to include usage examples and schema for both carousels and image posts. - Output of creation commands now always includes an `editorUrl` (PostNitro editor deep link). - Clarified that `--response-type DESIGN` skips rendering and returns only the design/editor link. - Removed the redundant skill-card.md file.","fileCount":8,"zipByteSize":14525},{"version":"1.0.1","createdAt":"2026-07-06T09:48:10.172Z","changelog":"postnitro 1.0.1 - Added new guidance clarifying that the skill is for PostNitro-powered carousel creation/scheduling, not as a general social-media strategy advisor. - Updated SKILL.md with a new \"When NOT to use\" note and explicit recommendations for content handoff, security, and local storage. - Included details on API key storage security (plaintext config file, no background processes, how to clear key). - Removed the redundant skill-card.md file.","fileCount":8,"zipByteSize":13015},{"version":"1.0.0","createdAt":"2026-07-04T18:40:34.973Z","changelog":"Initial release of the PostNitro skill. - Create multi-slide, on-brand social media carousels from a topic, article, or X thread. - Schedule posts to LinkedIn, Instagram, TikTok, and Threads via a single command. - Import custom slide content or generate slides with AI; export as PDF or PNG. - Fully supports end-to-end automation via JSON input/output for scripting or AI agents. - Requires a paid PostNitro API key for use; includes setup and authentication steps. - Includes detailed CLI usage, scheduling flows, and advanced patterns for repurposing content.","fileCount":8,"zipByteSize":12451}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17fhdpk451rztcqhmqcbkjwas885q1k:postnitro","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17fhdpk451rztcqhmqcbkjwas885q1k:postnitro` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/iammuneeb/postnitro before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iammuneeb-postnitro/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iammuneeb-postnitro/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iammuneeb-postnitro/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-iammuneeb-postnitro/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-iammuneeb-postnitro/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-iammuneeb-postnitro/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-12T12:40:28.421Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iammuneeb-postnitro/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iammuneeb-postnitro/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iammuneeb-postnitro/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iammuneeb-postnitro/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T23:35:32.750Z","emptyReason":null},"readme":"Skill: PostNitro\n\nOwner: iammuneeb\n\nSummary: Create on-brand social media carousels, single-image posts, and short videos, and schedule them to LinkedIn, Instagram, TikTok, and Threads from a single command. Turn a topic, article, or X thread into a finished multi-slide post, image, or video (with an optional audio track) — or import your own\n\nTags: latest:1.3.0\n\nVersion history:\n\nv1.3.0 | 2026-08-18T22:11:09.440Z | user\n\n**PostNitro 1.3.0 adds video creation and import.**\n\n- Added support for short video creation: generate or import slides as video scenes, with optional audio and MP4 output.\n- Introduced the `video generate` and `video import` commands.\n- Clarified output options: videos support `MP4` (single file) or `DESIGN` modes only.\n- Updated documentation to reflect video features and new CLI usage examples.\n- Added a video import example file.\n- Removed the old skill card markdown file.\n\nv1.2.1 | 2026-07-17T11:56:57.494Z | user\n\nAdds opt-in AI image generation (the Embed API's `generateImages` feature) and fixes the API base URL to the hosted endpoint.\n\n### Added\n- **AI image generation** (opt-in) on all generate/import commands and both one-shot commands: `--generate-images`, `--image-context <text>` (**required** when generating images), `--image-placement auto|background|in-line`, `--image-strategy strategic|all`. Best-effort — `--wait` results surface the `GENERATE_IMAGES` job step as `imageGeneration` (a COMPLETED post can still have a skipped/failed image step, e.g. free plan / over AI-image quota). AI images bill against the org's separate AI-image quota, not the post's slide credits.\n- `import-and-schedule` — one-shot import + schedule, the counterpart to `generate-and-schedule`. Takes `--slides` (carousel array) / `--slide` (single image) / `--slides-file`, plus `--post-type CAROUSEL|IMAGE`, the schedule options, and the AI-image flags. `--file` is the schedule body (as in `generate-and-schedule`). On scheduling failure it returns the `designId` so you can retry without re-importing.\n\n### Removed\n- The `--base-url` global flag and `POSTNITRO_API_BASE_URL` environment variable. The API base URL is now a fixed constant (`https://embed-api.postnitro.ai`) — PostNitro is hosted, not self-hosted, so the endpoint is always the same.\n\nv1.2.0 | 2026-07-17T11:47:27.838Z | user\n\nTracks the Embed API changes (IMAGE posts, `DESIGN` response type, `editorUrl`, infographic layout on images).\n\n### Added\n- `image generate | import | status | output | import-template` — single-image posts, mirroring the `carousel` commands. `image import` takes a **single slide object** (via `--slide`/`--file`), not an array, and supports the infographic layout (`layoutType`/`layoutConfig`).\n- `DESIGN` as a `--response-type` value — creates the editable design without rendering a PDF/PNG (returns `designId` + `editorUrl` only). Accepted anywhere `--response-type` is (generate/import, `image`, `generate-and-schedule`, `defaults set`).\n- `editorUrl` (deep link to open the design in the editor) surfaced in all generate/import/output results.\n- `--post-type CAROUSEL|IMAGE` on `generate-and-schedule`.\n\n### Changed\n- `--response-type` values are now validated/normalized (case-insensitive) to `PDF`/`PNG`/`DESIGN`; invalid values fail fast with a clear error.\n- The CLI still defaults `--response-type` to `PDF` and always sends it explicitly, so it is unaffected by the API's new `DESIGN` default for omitted values.\n- `carousel output` now reports `aspectRatio`/`editorUrl` and omits `data`/`mimeType`/`outputType` for `DESIGN` responses.\n\nv1.1.1 | 2026-07-17T11:45:54.847Z | user\n\nTracks the Embed API changes (IMAGE posts, `DESIGN` response type, `editorUrl`, infographic layout on images).\n\n### Added\n- `image generate | import | status | output | import-template` — single-image posts, mirroring the `carousel` commands. `image import` takes a **single slide object** (via `--slide`/`--file`), not an array, and supports the infographic layout (`layoutType`/`layoutConfig`).\n- `DESIGN` as a `--response-type` value — creates the editable design without rendering a PDF/PNG (returns `designId` + `editorUrl` only). Accepted anywhere `--response-type` is (generate/import, `image`, `generate-and-schedule`, `defaults set`).\n- `editorUrl` (deep link to open the design in the editor) surfaced in all generate/import/output results.\n- `--post-type CAROUSEL|IMAGE` on `generate-and-schedule`.\n\n### Changed\n- `--response-type` values are now validated/normalized (case-insensitive) to `PDF`/`PNG`/`DESIGN`; invalid values fail fast with a clear error.\n- The CLI still defaults `--response-type` to `PDF` and always sends it explicitly, so it is unaffected by the API's new `DESIGN` default for omitted values.\n- `carousel output` now reports `aspectRatio`/`editorUrl` and omits `data`/`mimeType`/`outputType` for `DESIGN` responses.\n\nv1.1.0 | 2026-07-13T15:34:49.243Z | user\n\n- Added support for single-image social posts via `image` commands, alongside multi-slide carousels.\n- Updated documentation to include usage examples and schema for both carousels and image posts.\n- Output of creation commands now always includes an `editorUrl` (PostNitro editor deep link).\n- Clarified that `--response-type DESIGN` skips rendering and returns only the design/editor link.\n- Removed the redundant skill-card.md file.\n\nv1.0.1 | 2026-07-06T09:48:10.172Z | user\n\npostnitro 1.0.1\n\n- Added new guidance clarifying that the skill is for PostNitro-powered carousel creation/scheduling, not as a general social-media strategy advisor.\n- Updated SKILL.md with a new \"When NOT to use\" note and explicit recommendations for content handoff, security, and local storage.\n- Included details on API key storage security (plaintext config file, no background processes, how to clear key).\n- Removed the redundant skill-card.md file.\n\nv1.0.0 | 2026-07-04T18:40:34.973Z | auto\n\nInitial release of the PostNitro skill.\n\n- Create multi-slide, on-brand social media carousels from a topic, article, or X thread.\n- Schedule posts to LinkedIn, Instagram, TikTok, and Threads via a single command.\n- Import custom slide content or generate slides with AI; export as PDF or PNG.\n- Fully supports end-to-end automation via JSON input/output for scripting or AI agents.\n- Requires a paid PostNitro API key for use; includes setup and authentication steps.\n- Includes detailed CLI usage, scheduling flows, and advanced patterns for repurposing content.\n\nArchive index:\n\nArchive v1.3.0: 9 files, 20616 bytes\n\nFiles: examples/EXAMPLES.md (4658b), examples/import-default.json (917b), examples/import-infographics.json (2322b), examples/import-video.json (2716b), examples/schedule-post.json (400b), references/cli-reference.md (17041b), skill-card.md (2380b), SKILL.md (21550b), _meta.json (128b)\n\nFile v1.3.0:SKILL.md\n\n---\nname: postnitro\ndescription: Create on-brand social media carousels, single-image posts, and short videos, and schedule them to LinkedIn, Instagram, TikTok, and Threads from a single command. Turn a topic, article, or X thread into a finished multi-slide post, image, or video (with an optional audio track) — or import your own content — then publish or draft it automatically. Fully scriptable (JSON in, JSON out), so an AI agent can run the entire create-to-schedule workflow. Use this skill whenever the user wants to create a carousel, image post, video, reel, slide post, or multi-slide content, repurpose an article, blog post, or X thread into slides or a video, or automate and schedule social media posts. Use it to create and schedule content through PostNitro, not as a general social-media strategy advisor. Requires a PostNitro API key.\nhomepage: https://postnitro.ai\nmetadata: {\"openclaw\":{\"emoji\":\"🎠\",\"primaryEnv\":\"POSTNITRO_API_KEY\",\"requires\":{\"bins\":[],\"env\":[\"POSTNITRO_API_KEY\"]}}}\n---\n\n# PostNitro — Create & Schedule Social Posts\n\nPostNitro creates on-brand social media posts — multi-slide carousels, single images, and short videos — and schedules them across LinkedIn, Instagram, TikTok, and Threads. This skill drives it from the command line, so an agent can take a topic, article, or your own content and produce a finished, scheduled post in one workflow. Every command is JSON in / JSON out — safe to script and chain.\n\n## Setup\n\n1. Install the CLI:\n   ```bash\n   npm install -g @postnitro/cli\n   ```\n2. Sign up at https://postnitro.ai and subscribe to a plan — the Embed API requires a **paid subscription** (no free tier). Then generate an API key at account settings → **Embed** → Generate API Key.\n3. Authenticate (in order of precedence: `--api-key` flag → env var → saved config):\n   ```bash\n   postnitro auth set-key pn-xxxx        # persists to ~/.postnitro-cli/config.json\n   export POSTNITRO_API_KEY=\"pn-xxxx\"    # or use an env var\n   ```\n4. Save defaults so you don't repeat template/brand/preset IDs on every call (the CLI's alternative to per-call flags — no env vars needed):\n   ```bash\n   postnitro defaults set --template-id <id> --brand-id <id> --preset-id <id> --response-type PDF\n   ```\n\n| Env var | Required | Purpose |\n|---------|----------|---------|\n| `POSTNITRO_API_KEY` | Yes* | API key (*unless passed via `--api-key` or saved with `auth set-key`) |\n\n> **Key rule:** `carousel generate`/`import` return an **`embedPostId`** (the async job). To *schedule* the result you need its **`designId`** (from the `--wait` output or `carousel output`). Never pass an `embedPostId` to `schedule`.\n\n> **Security:** `auth set-key` stores your API key in plaintext at `~/.postnitro-cli/config.json`. Restrict its file permissions and avoid shared or untrusted machines; run `auth clear` to remove it. This skill runs **no background processes, cron jobs, or startup scripts** — the only local state is the API key and saved defaults, both disclosed above.\n\n> **When NOT to use:** as a general social-media strategy advisor when no content is being produced. *(PostNitro composes with other tools — e.g., create a carousel here, then schedule it elsewhere — so pairing it with another scheduler is fine.)*\n\n## Core Workflow\n\nEvery create command is asynchronous — `--wait` handles the polling and returns the finished output (including `designId` and `editorUrl`) in one call.\n\n### 1. Create a post\n\nTwo independent choices decide which command you run:\n\n- **Post type** — a multi-slide `carousel`, a single `image`, or a `video`.\n- **Content source** — let AI write it (`generate`) or supply your own (`import`).\n\nThat's six commands:\n\n| | `generate` (AI writes it) | `import` (you supply content) |\n|---|---|---|\n| **`carousel`** (multi-slide) | `postnitro carousel generate` | `postnitro carousel import` |\n| **`image`** (single) | `postnitro image generate` | `postnitro image import` |\n| **`video`** (slides become scenes) | `postnitro video generate` | `postnitro video import` |\n\nAll six take `--template-id`/`--brand-id` (from flags or saved defaults) plus the modifiers in step 2, and every result includes the **`designId`** (needed to schedule) and an **`editorUrl`**.\n\n#### AI-generated (`generate`)\n\n```bash\npostnitro carousel generate \\\n  --context \"5 tips for growing your LinkedIn audience in 2026\" \\\n  --type text \\\n  --instructions \"Professional tone, actionable advice\" \\\n  --wait\n\n# Single image instead — same flags, just the image subcommand\npostnitro image generate --context \"Announce our new scheduling feature\" --wait\n\n# Video — same flags, plus the render length when you want the MP4 back\npostnitro video generate --context \"3 habits that make remote teams faster\" \\\n  --response-type MP4 --video-duration 30 --wait\n```\n\n**`--type` values:**\n- `text` — `--context` is the topic/text to turn into a post\n- `article` — `--context` is an article URL to extract and convert\n- `x` — `--context` is an X (Twitter) post/thread URL\n\n`generate` also needs an AI preset (`--preset-id`, or a saved default).\n\n#### Import your own content (`import`)\n\n```bash\n# Carousel — slides is an ARRAY of typed slides (inline --slides overrides --file)\npostnitro carousel import --slides '{\"slides\":[\n  {\"type\":\"starting_slide\",\"heading\":\"Your Title\",\"description\":\"Intro text\"},\n  {\"type\":\"body_slide\",\"heading\":\"Key Point\",\"description\":\"Details here\"},\n  {\"type\":\"ending_slide\",\"heading\":\"Take Action!\",\"cta_button\":\"Learn More\"}\n]}' --wait\npostnitro carousel import --file ./slides.json --wait\n\n# Single image — slide is a SINGLE OBJECT (not an array), via --slide\npostnitro image import --slide '{\"heading\":\"Welcome!\",\"sub_heading\":\"Subtitle\",\"cta_button\":\"Learn more\"}' --wait\n\n# Video — same slide ARRAY as a carousel; each slide is a scene\npostnitro video import --file ./scenes.json --response-type MP4 --video-duration 30 --wait\n```\n\n- **Carousel** (`--slides`, array): exactly 1 `starting_slide` (first), ≥1 `body_slide`, exactly 1 `ending_slide` (last); `heading` required on every slide. Run `postnitro carousel import-template` for the schema. Ready-to-use: [examples/import-default.json](examples/import-default.json), [examples/import-infographics.json](examples/import-infographics.json).\n- **Image** (`--slide`, one object): fields `heading` (required), `sub_heading`, `description`, `cta_button`, `image`, `background_image` (plus infographic — see step 2). Sending an array here is rejected. Run `postnitro image import-template` for the schema.\n- **Video** (`--slides`, array): the carousel rules exactly — each slide becomes a scene, in order. Run `postnitro video import-template` for the schema and the render settings.\n\n### 2. Options for any create command\n\nThese layer onto any of the four commands above (and onto `generate-and-schedule`).\n\n#### Output format — `--response-type PDF | PNG | DESIGN | MP4`\n\nDefault `PDF` (single file URL). `PNG` returns one URL per slide. `DESIGN` **skips rendering** — no file is produced; you get just the `designId` + `editorUrl`, the fastest option when you only need to schedule or edit.\n\n`MP4` (single video URL) belongs to `video` only, and a video accepts **nothing but** `MP4` or `DESIGN` — never `PDF`/`PNG`. Video commands default to `DESIGN`, so pass `--response-type MP4` when you want the file. `MP4` also can't be stored via `defaults set`, since it would break carousel and image calls.\n\n#### Video length & audio — `video` only\n\n```bash\npostnitro audio list                       # find an audio track's ID\npostnitro video generate --context \"...\" --response-type MP4 --video-duration 30 --audio-id <audioId> --wait\n```\n\n- `--video-duration <seconds>` — the **whole video's** length, not per scene. At least 5 and under 60. **Required** with `--response-type MP4`; optional for `DESIGN` (set it later in the editor).\n- `--audio-id <id>` — an audio **ID** from `postnitro audio list`, never a URL. Omit for a silent video. Uploading audio happens in the PostNitro app; the CLI can list (`audio list`) and delete (`audio delete <id> --yes`) but not upload.\n- Rendering a video takes longer than a carousel — typically 15-45s with `--wait` and `MP4`, longer for designs with animations or GIFs.\n- These same settings are reused automatically when the video is later scheduled as a reel.\n\n#### AI image generation — `--generate-images` (any post type, any source)\n\nOpt in to have AI generate images and bake them into the design before rendering. Works on **all six** create commands (and both one-shot commands) — carousels, images, and videos alike. Requires an `--image-context` brief:\n\n```bash\npostnitro carousel generate --context \"How scheduling saves marketers time\" \\\n  --generate-images --image-context \"upbeat and professional, product-focused\" \\\n  --image-placement auto --image-strategy all --wait\n```\n\n- `--image-context <text>` — **required** when generating images: a short visual brief for the image prompts\n- `--image-placement auto|background|in-line` (default `auto` — AI decides per slide)\n- `--image-strategy strategic|all` (`strategic` ≈ 50% of slides, default; `all` = every eligible slide)\n\n**Best-effort:** the post still completes if images fail or aren't permitted. With `--wait`, the result carries an `imageGeneration` field (the `GENERATE_IMAGES` step); if its `status` is `FAILED`, its `message` explains why (e.g. free plan can't generate AI images, or the org is over its AI-image quota). AI images bill against the org's **separate AI-image quota**, not the post's slide credits, and add latency. Without `--wait`, the same step shows up in `status` logs.\n\n#### Infographic layout — `import` only\n\nOn either `import` command, set `layoutType: \"infographic\"` on a slide (with a `layoutConfig`) to render data columns (max 3) instead of an image. Every column and content item needs a caller-provided `id`, and each item `description` is an HTML string. See `carousel import-template` / `image import-template` for the full schema.\n\n### 3. Check status / get output (only if you didn't use `--wait`)\n\n```bash\npostnitro carousel status <embedPostId>   # progress + step logs; poll until COMPLETED\npostnitro carousel output <embedPostId>   # final file URL(s) + designId + editorUrl\n```\n(`image status` / `image output` and `video status` / `video output` work identically for those post types.)\n\nOutput is a PDF (single URL), PNG (one URL per slide), or MP4 (single URL) in `data`, plus the `designId` and `editorUrl`. Those can be handed to another tool — e.g. a different scheduler — to publish on platforms PostNitro doesn't cover. With `--response-type DESIGN` there's no rendered file, so `data`/`mimeType`/`outputType` are omitted (you still get `designId` and `editorUrl`).\n\n### 4. Schedule the design to social accounts\n\n```bash\npostnitro social list   # get account IDs + platforms\n\npostnitro schedule create \\\n  --status SCHEDULED \\\n  --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --design-id <designId> \\\n  --selected-accounts '[\"<socialAccountId>\"]' \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"5–90 char title\"}' \\\n  --post-content '{\"common\":\"Caption with #hashtags\"}'\n```\n\n### 5. One-shot: create + schedule\n\nCreate and schedule in a single call — `generate-and-schedule` (AI writes it) or `import-and-schedule` (your own content). Both accept the schedule flags from step 4, `--post-type CAROUSEL|IMAGE|VIDEO` (with `--video-duration`/`--audio-id` for a video), and the AI-image options from step 2. If creation succeeds but scheduling fails, the error returns the `designId` so you can retry `schedule create` without re-creating (or re-spending credits).\n\n```bash\n# AI-generated\npostnitro generate-and-schedule \\\n  --context \"topic\" --type text \\\n  --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --selected-accounts '[\"<socialAccountId>\"]' \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"...\"}' \\\n  --post-content '{\"common\":\"...\"}'\n\n# Your own content — --slides (carousel array) or --slide (single image); --slides-file for a file.\n# (Here --file is the SCHEDULE body, so slides come from --slides / --slides-file.)\npostnitro import-and-schedule \\\n  --slides '{\"slides\":[ ... ]}' \\\n  --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --selected-accounts '[\"<socialAccountId>\"]' \\\n  --post-content '{\"common\":\"...\"}'\n```\n\n## Common Patterns\n\n### Pattern 1: LinkedIn thought-leadership carousel\n```bash\npostnitro carousel generate \\\n  --context \"5 mistakes startups make with their LinkedIn strategy and how to fix each one\" \\\n  --type text --instructions \"Professional but conversational. One clear takeaway per slide.\" --wait\n```\n\n### Pattern 2: Repurpose a blog post\n```bash\npostnitro carousel generate --context \"https://yourblog.com/posts/social-media-strategy-2026\" \\\n  --type article --instructions \"Extract the 5 most actionable points. Keep slide text concise.\" --wait\n```\n\n### Pattern 3: Repurpose an X thread\n```bash\npostnitro carousel generate --context \"https://x.com/username/status/1234567890\" \\\n  --type x --instructions \"Maintain the original voice and key points\" --wait\n```\n\n### Pattern 4: Data-driven infographic carousel\nImport slides with `layoutType: \"infographic\"` body slides — see\n[examples/import-infographics.json](examples/import-infographics.json).\n\n### Pattern 5: Video reel with an audio track\n```bash\nAUDIO=$(postnitro audio list | jq -r '.audios[0].id')\npostnitro video generate --context \"3 habits that make remote teams faster\" --type text \\\n  --response-type MP4 --video-duration 30 --audio-id \"$AUDIO\" --wait\n```\nA reel reuses the video's own duration and audio when scheduled, so `--post-settings` is\noptional — omit it and the API fills it in (falling back to 30s with no audio).\n\n### Pattern 6: Audit one account's schedule\n```bash\nLINKEDIN=$(postnitro social list | jq -r 'first(.accounts[] | select(.platform==\"linkedin\").id)')\npostnitro schedule list --from 2026-09-01 --to 2026-09-30 --accounts \"$LINKEDIN\"\n```\n`--accounts` filters the **posts**, not the accounts inside them: a post targeting LinkedIn\nand Instagram is returned when you filter by either, and it still lists both accounts.\n\n### Pattern 7: Generate → schedule to LinkedIn\n```bash\nDID=$(postnitro carousel generate --context \"5 remote work habits\" --type text --wait | jq -r .designId)\nLINKEDIN=$(postnitro social list | jq -r 'first(.accounts[] | select(.platform==\"linkedin\").id)')\npostnitro schedule create --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --design-id \"$DID\" --selected-accounts \"[\\\"$LINKEDIN\\\"]\" \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"5 remote work habits\"}' \\\n  --post-content '{\"common\":\"New carousel 🚀 #remotework\"}'\n```\n\n### Pattern 6: Batch scheduling\n```bash\nDATES=(\"2026-02-14T09:00:00Z\" \"2026-02-15T09:00:00Z\")\nTOPICS=(\"Monday motivation 💪\" \"Tuesday tips 💡\")\nfor i in \"${!DATES[@]}\"; do\n  postnitro generate-and-schedule --context \"${TOPICS[$i]}\" --type text \\\n    --status SCHEDULED --scheduled-at \"${DATES[$i]}\" \\\n    --selected-accounts '[\"<socialAccountId>\"]' \\\n    --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"Daily post\"}'\ndone\n```\n\n## Content Strategy Tips\n\n- **LinkedIn**: professional tone, actionable insights, 6–10 slides, clear CTA. PDF carousels post as `postType: \"document\"` (needs a 5–90 char `postTitle`).\n- **Instagram**: visual-first, concise text, 5–8 slides, storytelling arc. `postAsStory` for stories.\n- **TikTok**: trendy, punchy, 4–7 slides, hook on slide 1.\n- **X / Threads**: data-driven, 3–6 slides, provocative opening.\n\n## Common Gotchas\n\n1. **Not authenticated** — run `postnitro auth status`; set a key before anything else.\n2. **Scheduling with `embedPostId`** — use the **`designId`** from `--wait`/`carousel output`, never the `embedPostId`.\n3. **`Scheduled at is in the past`** — `--scheduled-at` must be a future ISO-8601 datetime with a trailing `Z`.\n4. **Invalid inline JSON** — wrap JSON flags in single quotes; the CLI validates before any network call.\n5. **`Missing --brand-id ... multiple candidates`** — pass the ID or save a default with `defaults set`.\n6. **LinkedIn `document` rejected** — `postType:\"document\"` needs a 5–90 char `postTitle`.\n7. **Empty post** — a scheduled post needs either `--design-id` or non-empty `--post-content`.\n8. **Destructive commands** — `social disconnect` and `schedule delete` require `--yes`.\n9. **`SCHEDULED` publishes live** — use `DRAFT` when unsure; confirm time/account with the user first.\n10. **`responseType`** — the CLI defaults to `PDF` (pass `--response-type PNG` for individual slide images, or `DESIGN` to skip rendering and only create the design). Note: the underlying API now defaults to `DESIGN` when omitted, but the CLI always sends `PDF` explicitly, so CLI behavior is unchanged.\n11. **Credits vary** — AI generation ≈ 2 credits/slide; content import ≈ 1 credit/slide. Warn before large batches.\n\n## Credits & Pricing\n\nThe Embed API requires a **paid subscription** — there is no free tier, and free accounts cannot call the API. See **https://postnitro.ai/plans** for current plans and credit allowances.\n\nApproximate usage cost (observed):\n- Content import: ~1 credit per slide\n- AI generation: ~2 credits per slide\n\n## Supporting Resources\n\n**In this skill:**\n- [references/cli-reference.md](references/cli-reference.md) — complete command, platform-settings, and slide-schema reference\n- [examples/EXAMPLES.md](examples/EXAMPLES.md) — ready-to-use import & schedule JSON (`import-default.json`, `import-infographics.json`, `schedule-post.json`)\n\n**Full project docs (GitHub):**\n- [README](https://github.com/postnitro/postnitro-agent#readme) — full command reference\n- [QUICK_START.md](https://github.com/postnitro/postnitro-agent/blob/main/QUICK_START.md) — zero to a scheduled carousel in minutes\n- [HOW_TO_RUN.md](https://github.com/postnitro/postnitro-agent/blob/main/HOW_TO_RUN.md) — install & run methods\n- [PLATFORM_SETTINGS.md](https://github.com/postnitro/postnitro-agent/blob/main/PLATFORM_SETTINGS.md) — platform settings schemas\n- [FEATURES.md](https://github.com/postnitro/postnitro-agent/blob/main/FEATURES.md) — full feature list\n- Per-command help: `postnitro <command> <subcommand> --help`\n\n## Quick Reference\n\n```bash\n# Auth (do this first)\npostnitro auth set-key pn-xxxx | postnitro auth status | export POSTNITRO_API_KEY=pn-xxxx\n\n# Discover + defaults\npostnitro template list | brand list | preset list | social list\npostnitro defaults set --template-id <id> --brand-id <id> --preset-id <id> --response-type PDF\n\n# Create (async — use --wait; result has designId + editorUrl)\n# --response-type PDF|PNG|DESIGN (DESIGN skips rendering; CLI default is PDF)\n# Optional AI images (any generate/import): --generate-images --image-context \"brief\" [--image-placement auto|background|in-line] [--image-strategy strategic|all]\npostnitro carousel generate --context \"topic|url\" --type text|article|x [--instructions \"...\"] --wait\npostnitro carousel import (--slides '{\"slides\":[...]}' | --file ./slides.json) --wait\npostnitro carousel status <embedPostId>        # if not using --wait\npostnitro carousel output <embedPostId>        # file URLs + designId + editorUrl\n\n# Single-image posts (mirror carousel; import takes ONE slide object, not an array)\npostnitro image generate --context \"topic|url\" --type text|article|x --wait\npostnitro image import (--slide '{\"heading\":\"...\"}' | --file ./slide.json) --wait\n\n# Schedule (date REQUIRED + future; use designId, not embedPostId)\npostnitro schedule create --status SCHEDULED|DRAFT --scheduled-at \"<iso>\" --design-id <id> \\\n  --selected-accounts '[\"<id>\"]' --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"...\"}' \\\n  --post-content '{\"common\":\"caption\"}'\npostnitro schedule list --from \"<date>\" --to \"<date>\" | get <id> | delete <id> --yes\n\n# One-shot: create + schedule (both take --post-type + AI-image flags)\npostnitro generate-and-schedule --context \"topic\" --status SCHEDULED --scheduled-at \"<iso>\" ...\npostnitro import-and-schedule --slides '{\"slides\":[...]}' --status SCHEDULED --scheduled-at \"<iso>\" ...   # or --slide for image\n```\n\n## Tips for the Agent\n\n- Always confirm authentication (`postnitro auth status`) before running any other command. Never fabricate an API key — ask the user.\n- Prefer `--wait` so one call returns the finished output and `designId`.\n- Discover IDs with the `list` commands; save workspace defaults with `defaults set` so later calls stay short.\n- **Schedule with the `designId`, not the `embedPostId`.**\n- For `--type article`/`x`, `--context` must be a URL. For plain text, use `--type text`.\n- `responseType` defaults to PDF in the CLI — pass `--response-type PNG` for individual slide images, or `DESIGN` to skip rendering when you only need the `designId`/`editorUrl` (e.g. for scheduling).\n- `--scheduled-at` must be a **future** ISO-8601 datetime (trailing `Z`).\n- `status: SCHEDULED` creates a **live** post that will publish — confirm the time and account with the user, or use `DRAFT` when unsure.\n- Parse stdout as JSON; on failure read `.error.message` from stderr and fix the inputs.\n- Warn about credit costs before large batches (AI generation is ~2× the cost of import).\n- If the user doesn't specify a platform, suggest LinkedIn (most common carousel use case) and remember PDF carousels post there as `document`.\n\nFile v1.3.0:_meta.json\n\n{\n  \"ownerId\": \"kn75qwv6mp7qy963qgzggb2qrn815sm8\",\n  \"slug\": \"postnitro\",\n  \"version\": \"1.3.0\",\n  \"publishedAt\": 1787091069440\n}\n\nFile v1.3.0:references/cli-reference.md\n\n# PostNitro CLI — Command Reference\n\nComplete reference for `@postnitro/cli`. Every command prints JSON on stdout (exit 0) or a\n`{ \"success\": false, \"error\": { \"message\": ... } }` object on stderr (exit 1).\n\n## Global options\n\nAvailable on every command:\n\n| Flag | Purpose |\n|------|---------|\n| `--api-key <key>` | API key (overrides env/saved config) |\n| `-V, --version` | Print version |\n| `-h, --help` | Help for any command/subcommand |\n\n## auth\n\n```\npostnitro auth set-key <key>   # save to ~/.postnitro-cli/config.json\npostnitro auth status          # { configured, source, apiKey (masked) }\npostnitro auth clear           # remove saved key\n```\n\n> **Security:** `auth set-key` stores the API key in **plaintext** at `~/.postnitro-cli/config.json`. Restrict its file permissions (`chmod 600`), avoid shared or untrusted machines, and run `auth clear` to remove it. In CI, prefer `--api-key` or the `POSTNITRO_API_KEY` env var over the saved file.\n\n## defaults\n\n```\npostnitro defaults get\npostnitro defaults set [--template-id <id>] [--brand-id <id>] [--preset-id <id>] [--response-type PDF|PNG|DESIGN]\n```\nRequires at least one field. Resolution order per field: explicit flag → saved default → auto-select (when exactly one candidate exists).\n\n## template / brand / preset (discovery)\n\n```\npostnitro template list [--page <n>] [--limit <n>]\npostnitro preset list   [--page <n>] [--limit <n>]\npostnitro brand list    [--page <n>] [--limit <n>]\npostnitro brand get <id>\npostnitro brand create  (--name --handle --image [--company-detail] [--no-show-name|--no-show-handle|--no-show-image]) | --data <json> | --file <json>\npostnitro brand update <id> ...same as create...\n```\n`--data` (inline JSON object) overrides `--file`, which overrides the individual flags.\n\n## carousel\n\n```\npostnitro carousel import-template                 # prints the slide schema + rules\npostnitro carousel generate --context <text> [--type text|article|x] [--instructions <text>]\n                            [--template-id] [--brand-id] [--preset-id] [--response-type PDF|PNG|DESIGN]\n                            [--requestor-id <id>] [--wait]\npostnitro carousel import (--slides <json> | --file <path>)\n                          [--template-id] [--brand-id] [--response-type] [--requestor-id] [--wait]\npostnitro carousel status <embedPostId>            # progress + step logs\npostnitro carousel output <embedPostId>            # file URL(s) + designId + editorUrl\n```\n- `--type`: `text` (topic/text), `article` (article URL), `x` (X post URL).\n- `--response-type`: `PDF` (default) | `PNG` | `DESIGN`. `DESIGN` skips rendering — no file is produced, output has `designId` + `editorUrl` only.\n- `--wait`: poll to completion; returns final output incl. `designId` and `editorUrl`.\n- `--slides` (inline JSON) overrides `--file`; accepts a bare array or `{ \"slides\": [...] }`.\n- AI images: add `--generate-images` (+ optional `--image-placement`/`--image-strategy`/`--image-context`) — see [AI image generation](#ai-image-generation-generateimages).\n\n## image\n\nSingle-image posts. Mirrors `carousel`, but produces one image and `import` takes a **single slide object** (not an array).\n\n```\npostnitro image import-template                    # prints the image-slide schema + rules\npostnitro image generate --context <text> [--type text|article|x] [--instructions <text>]\n                         [--template-id] [--brand-id] [--preset-id] [--response-type PDF|PNG|DESIGN]\n                         [--requestor-id <id>] [--wait]\npostnitro image import (--slide <json> | --file <path>)\n                       [--template-id] [--brand-id] [--response-type] [--requestor-id] [--wait]\npostnitro image status <embedPostId>               # progress + step logs\npostnitro image output <embedPostId>               # file URL(s) + designId + editorUrl\n```\n- `--slide` (inline JSON) overrides `--file`; a **single object** (arrays are rejected — those are CAROUSEL-only). Accepts a bare object or `{ \"slides\": { ... } }`.\n- Allowed slide fields: `heading` (required), `sub_heading`, `description`, `cta_button`, `image`, `background_image`, plus `layoutType`/`layoutConfig` for the infographic layout. Any other field is rejected.\n- Infographic layout works on IMAGE too — set `layoutType: \"infographic\"` + `layoutConfig` (same schema as carousel; see below). Every column and content item needs a caller-provided `id`.\n- AI images: `--generate-images` (+ optional flags) works here too — see [AI image generation](#ai-image-generation-generateimages).\n\n## video\n\nVideo posts. Slides are **scenes**, so `import` takes the same slide **array** as `carousel`; the extra input is the render length (and an optional audio track).\n\n```\npostnitro video import-template                    # prints the slide rules + video settings\npostnitro video generate --context <text> [--type text|article|x] [--instructions <text>]\n                         [--template-id] [--brand-id] [--preset-id] [--response-type MP4|DESIGN]\n                         [--video-duration <seconds>] [--audio-id <id>]\n                         [--requestor-id <id>] [--wait]\npostnitro video import (--slides <json> | --file <path>)\n                       [--template-id] [--brand-id] [--response-type MP4|DESIGN]\n                       [--video-duration <seconds>] [--audio-id <id>] [--requestor-id] [--wait]\npostnitro video status <embedPostId>               # progress + step logs\npostnitro video output <embedPostId>               # MP4 URL + designId + editorUrl\n```\n- **Response types:** only `MP4` (renders the video) and `DESIGN` (no render — finish it in the video maker). `PDF`/`PNG` are rejected for a video, and `MP4` is rejected for every other post type. Video commands default to `DESIGN`; a saved `PDF`/`PNG` default is treated as `DESIGN` with a note in `warnings`.\n- `--video-duration <seconds>`: the **whole video's** length, not per scene. At least 5, under 60. **Required** with `--response-type MP4`; optional for `DESIGN`.\n- `--audio-id <id>`: an audio **ID** from `postnitro audio list` — never a URL. The API rejects a URL, an ID from another workspace, or an ID naming a non-audio file. Omit for a silent video.\n- Slides follow the carousel rules exactly (1 `starting_slide` first, ≥1 `body_slide`, 1 `ending_slide` last); infographic layouts work on scenes too.\n- Rendering a video is slower than a carousel — typically 15-45s for `--wait` with `MP4`, and longer for designs with animations or GIFs (which use the enhanced renderer).\n- The duration/audio carry over automatically when the video is scheduled as a reel, so `--post-settings` is usually unnecessary.\n- AI images: `--generate-images` (+ optional flags) works here too — see [AI image generation](#ai-image-generation-generateimages).\n\n## audio\n\nAudio tracks used by video posts (`--audio-id`) and scheduled reels (`postSettings.audioId`). **Upload happens in the PostNitro app** — the CLI lists and deletes only.\n\n```\npostnitro audio list [--page <n>] [--limit <n>]   # { count, audios: [{ id, name, url, duration, artistName, source, createdAt }] }\npostnitro audio delete <id> --yes                 # destructive\n```\n- `id` is the value to pass as `--audio-id` / `postSettings.audioId`. `url` is for previewing; the API always wants the ID.\n- `duration` is the **track's** length in seconds and is independent of `--video-duration` — a longer track is simply cut off at the video's length.\n- An empty list means the workspace has no audio yet; the result includes a `note` saying so. Create the video without `--audio-id`, or upload a track in the app first.\n- **Destructive:** `audio delete` permanently removes the record and the stored file. It is refused (400) while a scheduled post still references the track — remove it from those posts first. Videos already rendered to MP4 keep their audio, since the track is baked into the file. Requires `--yes`.\n\n## AI image generation (`generateImages`)\n\nOpt-in AI image generation, available on **every** generate/import command (carousel, image, and video) and on `generate-and-schedule`. Images are generated and baked into the design before rendering, so they appear in the rendered file and in the editor.\n\n| Flag | Values | Default | Notes |\n|------|--------|---------|-------|\n| `--generate-images` | (boolean) | off | Opt in. Also implied by any flag below. |\n| `--image-context <text>` | string | — | **Required** when generating images: a short visual brief for the image prompts. |\n| `--image-placement <mode>` | `auto` \\| `background` \\| `in-line` | `auto` | `auto` = AI decides per slide. |\n| `--image-strategy <mode>` | `strategic` \\| `all` | `strategic` | `strategic` ≈ 50% of slides; `all` = every eligible slide. |\n\n- `--image-context` is required whenever image generation is enabled — the CLI fails fast if it's missing.\n- The two enums are validated client-side (fails fast on a bad value).\n- **Best-effort:** the post still completes if image generation fails or isn't permitted. With `--wait`, the result includes `imageGeneration` (the `GENERATE_IMAGES` job step); a `FAILED` status there (e.g. free plan, or over the org's AI-image quota) means the post completed without images. Without `--wait`, the step appears in `status` logs.\n- **Credits:** AI images consume the organization's **separate AI-image quota** — the post's slide-based `credits` are unchanged. Free plans cannot generate AI images.\n- Adds latency (real images are rendered); keep polling `status` until `COMPLETED`.\n\n## social\n\n```\npostnitro social list                 # { count, accounts: [{ id, platform, handle, name, accountType, status }] }\npostnitro social get <id>\npostnitro social disconnect <id> --yes # destructive\n```\n\n> **Destructive:** `social disconnect` removes the linked social account from your workspace. Scheduled posts targeting it will fail to publish, and restoring access requires reconnecting and re-authenticating. Requires `--yes`.\n\n## schedule\n\n```\npostnitro schedule list --from <date> --to <date> [--accounts <id,id>]\npostnitro schedule create --status DRAFT|SCHEDULED --scheduled-at <iso>\n                          [--design-id <id>] [--file <json>]\n                          [--post-content <json>] [--selected-accounts <json>]\n                          [--instagram-post-settings <json>] [--tiktok-post-settings <json>]\n                          [--linkedin-post-settings <json>] [--threads-post-settings <json>]\n                          [--post-settings <json>]\npostnitro schedule get <id>\npostnitro schedule update <id> ...same flags as create...   # REPLACES state\npostnitro schedule delete <id> --yes\n```\n- **`schedule delete` is destructive:** it permanently cancels and removes the scheduled post — this cannot be undone. Requires `--yes`.\n- Requires either `--design-id` or non-empty `--post-content`.\n- `--scheduled-at` must be a **future** ISO-8601 datetime (trailing `Z`).\n- Inline JSON flags override the same field in `--file`.\n- `--accounts <id,id>` (list only) filters by social account — comma-separated IDs from `postnitro social list`. It filters **posts**, not the accounts within them: a post targeting two platforms is returned when you filter by either, and it still reports every account it targets. Unknown IDs match nothing rather than erroring.\n- `--post-settings` carries a reel's video settings (`{\"videoDuration\":30,\"audioId\":\"...\"}`) and is **optional**: when omitted, the API fills each field 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; `audioId` must be an audio ID in your workspace.\n\n## generate-and-schedule\n\n```\npostnitro generate-and-schedule --context <text> --status DRAFT|SCHEDULED --scheduled-at <iso>\n                                [--post-type CAROUSEL|IMAGE|VIDEO] [--video-duration <s>] [--audio-id <id>]\n                                [ ...all generate flags... ]\n                                [--generate-images --image-context <text> ...]   # optional AI images\n                                [--design-id] [--file <json>]\n                                [--post-content] [--selected-accounts] [--*-post-settings] [--post-settings]\n```\nGenerates → waits → schedules in one call. `--post-type` defaults to `CAROUSEL` (use `IMAGE` for a single-image post, or `VIDEO` for a video — `VIDEO` also takes `--video-duration`/`--audio-id`, and only `MP4`/`DESIGN` response types). Also accepts the [AI image generation](#ai-image-generation-generateimages) flags. On scheduling failure the error includes the `designId` so you can retry `schedule create` without regenerating.\n\n## import-and-schedule\n\n```\npostnitro import-and-schedule --status DRAFT|SCHEDULED --scheduled-at <iso>\n                              [--post-type CAROUSEL|IMAGE|VIDEO] [--video-duration <s>] [--audio-id <id>]\n                              (--slides <json> | --slide <json> | --slides-file <path>)\n                              [--template-id] [--brand-id] [--response-type] [--requestor-id]\n                              [--generate-images --image-context <text> ...]   # optional AI images\n                              [--design-id] [--file <json>]\n                              [--post-content] [--selected-accounts] [--*-post-settings] [--post-settings]\n```\nImports your own content → waits → schedules in one call (the import-side counterpart of `generate-and-schedule`). `--post-type` defaults to `CAROUSEL` — pass `--slides` (array) for CAROUSEL or VIDEO, or `--slide` (single object) for IMAGE; `--slides-file` reads either from a file. A VIDEO also takes `--video-duration`/`--audio-id`.\n\n> **Flag note:** here `--file` is the **schedule body** (postContent/accounts/settings), matching `generate-and-schedule` — so slide content comes from `--slides` / `--slide` / `--slides-file`, not `--file`.\n\nAlso accepts the [AI image generation](#ai-image-generation-generateimages) flags. On scheduling failure the error includes the `designId` so you can retry `schedule create` without re-importing.\n\n---\n\n## Captions — `postContent`\n\nJSON object keyed by platform. At least one non-empty caption unless `--design-id` is set. Hashtags auto-extracted.\nKeys: `common`, `linkedin`, `instagram`, `tiktok`, `facebook`, `threads`.\n\n## Platform settings\n\n| Flag | Shape |\n|------|-------|\n| `--linkedin-post-settings` | `{\"postType\":\"carousel\\|document\\|image\\|reel\",\"postTitle\":\"...\"}` — `document` needs 5–90 char `postTitle` |\n| `--instagram-post-settings` | `{\"postType\":\"carousel\\|image\\|reel\",\"postAsStory\":false}` |\n| `--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}` |\n| `--threads-post-settings` | `{\"postType\":\"carousel\\|image\\|reel\"}` |\n| `--post-settings` (reel) | `{\"videoDuration\":30,\"audioId\":\"...\"}` |\n\n## Slide schema (import)\n\nFor **carousel** import: exactly one `starting_slide` (first), ≥1 `body_slide`, exactly one `ending_slide` (last). For **image** import it's a single object with no `type` field (see the `image` section above).\n\n| Field | Notes |\n|-------|-------|\n| `type` | `starting_slide` \\| `body_slide` \\| `ending_slide` (required) |\n| `heading` | required on every slide |\n| `sub_heading` | optional |\n| `description` | optional body text |\n| `image` | optional image URL (public); ignored if `layoutType: \"infographic\"` |\n| `background_image` | optional background URL |\n| `cta_button` | optional CTA text |\n| `layoutType` | `default` \\| `infographic` |\n| `layoutConfig` | required when `layoutType: \"infographic\"` |\n\nInfographic `layoutConfig` (works on both carousel and image slides):\n```json\n{\n  \"hasHeader\": true,\n  \"columnCount\": 1,\n  \"displayCounterAs\": \"counter\",  // \"counter\" (default) | \"none\"\n  \"columnDisplay\": \"grid\",        // \"grid\" (comparative, default) or \"cycle\" (sequential; data in FIRST column only)\n  \"columnData\": [\n    {\n      \"id\": \"col-1\",\n      \"header\": \"Column\",\n      \"content\": [\n        {\n          \"id\": \"item-1\",\n          \"icon\": null,\n          \"title\": \"Item\",\n          \"description\": \"<p dir=\\\"ltr\\\">HTML string</p>\",\n          \"titleEnabled\": true,\n          \"descriptionEnabled\": true\n        }\n      ]\n    }\n  ]\n}\n```\nMax 3 columns. Setting `layoutType: \"infographic\"` replaces the slide's `image`. **Every column and content item needs a caller-provided `id`** — the API does not auto-generate them. `description` is an HTML string. Omitted `layoutConfig` fields use the defaults above; if `layoutType` is `infographic` but `layoutConfig` is missing, the slide falls back to the default layout.\n\n## Environment variables\n\n| Variable | Default | Purpose |\n|----------|---------|---------|\n| `POSTNITRO_API_KEY` | – | API key |\n| `POSTNITRO_CONFIG_DIR` | `~/.postnitro-cli` | Config/defaults location |\n\nFile v1.3.0:examples/EXAMPLES.md\n\n# PostNitro CLI — Skill Examples\n\nReady-to-use files for the `postnitro` skill. Authenticate first\n(`postnitro auth set-key pn-...` or `export POSTNITRO_API_KEY=pn-...`).\n\n## Files\n\n| File | What it is | Use with |\n|------|------------|----------|\n| [import-default.json](import-default.json) | Basic 4-slide import (starting / body / body / ending) | `carousel import` |\n| [import-infographics.json](import-infographics.json) | Import with `grid` and `cycle` infographic body slides | `carousel import` |\n| [import-video.json](import-video.json) | 4-scene video import — background image, inline image, and an infographic scene (same slide array as a carousel) | `video import` |\n| [schedule-post.json](schedule-post.json) | A full `schedule` body (designId + accounts + caption + LinkedIn settings) | `schedule create --file` |\n\n## Import a carousel\n\n```bash\n# From a file\npostnitro carousel import --file examples/import-default.json --wait\n\n# With infographic slides\npostnitro carousel import --file examples/import-infographics.json --wait\n\n# Same JSON inline (overrides --file)\npostnitro carousel import --slides \"$(cat examples/import-default.json)\" --wait\n```\n\n## Import a video\n\nScenes use the same slide array as a carousel — one slide per scene. `--video-duration` is\nrequired when you want the rendered MP4 back.\n\n```bash\n# Rendered MP4, silent\npostnitro video import --file examples/import-video.json \\\n  --response-type MP4 --video-duration 30 --wait\n\n# With an audio track (IDs come from `postnitro audio list`, never a URL)\nAUDIO=$(postnitro audio list | jq -r '.audios[0].id')\npostnitro video import --file examples/import-video.json \\\n  --response-type MP4 --video-duration 30 --audio-id \"$AUDIO\" --wait\n\n# Design only — no render; set the duration later in the video maker\npostnitro video import --file examples/import-video.json --wait\n```\n\nA scene holds anything a carousel slide does — `image`, `background_image`, and\n`layoutType: \"infographic\"` all work, which is why this example uses one of each.\n\n**Want actual motion?** Point an `image` or `background_image` at a **`.gif`** (or use a\ntemplate whose elements carry animations). The API renders those through its enhanced\nvideo pipeline, which captures the movement; without a GIF or animations you get a\nstatic scene-by-scene video. Expect the enhanced render to take longer than the\n15-45s a plain one does.\n\n## Generate with AI (no JSON file needed — flags only)\n\n```bash\npostnitro carousel generate --context \"5 LinkedIn growth tips\" --type text --wait\npostnitro carousel generate --context \"https://yourblog.com/post\" --type article --wait\npostnitro carousel generate --context \"https://x.com/user/status/123\" --type x --wait\n\n# A video instead — each AI-written slide becomes a scene\npostnitro video generate --context \"3 habits that make remote teams faster\" \\\n  --response-type MP4 --video-duration 30 --wait\n```\n\n## Schedule a finished design\n\nEdit `schedule-post.json` (set a real `designId` from the import/generate output and a real\n`socialAccountId` from `postnitro social list`), then:\n\n```bash\npostnitro schedule create --file examples/schedule-post.json\n```\n\nInline flags override any field in the file, e.g. change the time without editing the file:\n\n```bash\npostnitro schedule create --file examples/schedule-post.json --scheduled-at \"2027-01-15T09:00:00Z\"\n```\n\n## End-to-end (capture designId → schedule)\n\n```bash\nDID=$(postnitro carousel import --file examples/import-infographics.json --wait | jq -r .designId)\nLINKEDIN=$(postnitro social list | jq -r 'first(.accounts[] | select(.platform==\"linkedin\").id)')\npostnitro schedule create --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --design-id \"$DID\" --selected-accounts \"[\\\"$LINKEDIN\\\"]\" \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"Remote Work, Done Right\"}' \\\n  --post-content '{\"common\":\"New carousel 🚀 #remotework\"}'\n```\n\n## Audio tracks\n\n```bash\npostnitro audio list                    # ids for --audio-id / postSettings.audioId\npostnitro audio delete <audioId> --yes  # destructive; refused while a scheduled post uses it\n```\n\nUploading audio happens in the PostNitro app — the CLI lists and deletes only. An empty\n`audios` array means there's nothing uploaded yet; create the video without `--audio-id`.\n\n## What's scheduled on one account\n\n```bash\nLINKEDIN=$(postnitro social list | jq -r 'first(.accounts[] | select(.platform==\"linkedin\").id)')\npostnitro schedule list --from 2026-09-01 --to 2026-09-30 --accounts \"$LINKEDIN\"\n```\n\nSee [../references/cli-reference.md](../references/cli-reference.md) for the full command and schema reference.\n\nFile v1.3.0:skill-card.md\n\n## Description:\n\nPostNitro helps an agent create, import, render, and schedule on-brand carousels, single-image social posts, and short videos across LinkedIn, Instagram, TikTok, and Threads using the PostNitro CLI.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[iammuneeb](https://clawhub.ai/user/iammuneeb)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users, marketers, developers, and agents use this skill to turn topics, articles, X threads, or structured slide JSON into draft or scheduled PostNitro social posts and videos.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill depends on the external @postnitro/cli package and a PostNitro API key with access to connected social accounts.\n\nMitigation: Install only when the package and account access are trusted, and prefer a scoped, temporary, or environment-provided API key.\n\nRisk: Saved authentication can store the PostNitro API key in plaintext on the local machine.\n\nMitigation: Prefer the POSTNITRO_API_KEY environment variable or --api-key flag on shared machines, restrict saved config file permissions, and clear saved auth when it is no longer needed.\n\nRisk: SCHEDULED actions can publish live social content to selected accounts at the configured time.\n\nMitigation: Confirm the target accounts, post content, and scheduled time before scheduling, and use DRAFT when the user is unsure.\n\n## Reference(s):\n\n- [PostNitro Skill Page](https://clawhub.ai/iammuneeb/skills/postnitro)\n- [PostNitro Homepage](https://postnitro.ai)\n- [CLI Reference](references/cli-reference.md)\n- [Skill Examples](examples/EXAMPLES.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with bash commands and JSON payloads]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Outputs may include PostNitro CLI commands that create, render, draft, or schedule social media content through a connected PostNitro account.]\n\n## Skill Version(s):\n\n1.3.0 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.3.0:examples/import-default.json\n\n{\n  \"slides\": [\n    {\n      \"type\": \"starting_slide\",\n      \"heading\": \"5 LinkedIn Growth Tips\",\n      \"sub_heading\": \"For founders and creators\",\n      \"description\": \"Simple habits that compound into real reach.\",\n      \"cta_button\": \"Swipe →\"\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"Post when your audience is awake\",\n      \"description\": \"Check your analytics for peak hours and schedule around them, not around when you happen to be free.\"\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"Hook in the first line\",\n      \"description\": \"The first sentence decides whether anyone reads the rest. Lead with the payoff, not the setup.\"\n    },\n    {\n      \"type\": \"ending_slide\",\n      \"heading\": \"Pick one and start today\",\n      \"sub_heading\": \"Consistency beats intensity\",\n      \"description\": \"Follow for more practical growth playbooks.\",\n      \"cta_button\": \"Follow\"\n    }\n  ]\n}\n\nFile v1.3.0:examples/import-infographics.json\n\n{\n  \"slides\": [\n    {\n      \"type\": \"starting_slide\",\n      \"heading\": \"Remote Work, Done Right\",\n      \"sub_heading\": \"A 2-minute field guide\",\n      \"description\": \"The setup and habits that separate good remote workers from great ones.\",\n      \"cta_button\": \"Swipe →\"\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"The 4 pillars of a solid setup\",\n      \"description\": \"Get these right and everything else gets easier.\",\n      \"layoutType\": \"infographic\",\n      \"layoutConfig\": {\n        \"columnCount\": 2,\n        \"columnDisplay\": \"grid\",\n        \"displayCounterAs\": \"none\",\n        \"hasHeader\": true,\n        \"columnData\": [\n          {\n            \"header\": \"Space & Focus\",\n            \"content\": [\n              { \"title\": \"Dedicated Desk\", \"description\": \"A fixed spot signals to your brain that it's work time.\" },\n              { \"title\": \"Noise Control\", \"description\": \"Headphones or a closed door — pick one.\" }\n            ]\n          },\n          {\n            \"header\": \"Rhythm & Recovery\",\n            \"content\": [\n              { \"title\": \"Hard Stop Time\", \"description\": \"Set an end time and honor it.\" },\n              { \"title\": \"Lunch Away\", \"description\": \"Take 30 screen-free minutes.\" }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"A simple daily cadence\",\n      \"description\": \"Run your day in sequence, not in chaos.\",\n      \"layoutType\": \"infographic\",\n      \"layoutConfig\": {\n        \"columnCount\": 1,\n        \"columnDisplay\": \"cycle\",\n        \"displayCounterAs\": \"counter\",\n        \"hasHeader\": false,\n        \"columnData\": [\n          {\n            \"header\": \"Daily Flow\",\n            \"content\": [\n              { \"title\": \"Deep work first\", \"description\": \"90 minutes on the hardest task before any meetings.\" },\n              { \"title\": \"Batch comms\", \"description\": \"Two windows for Slack/email — not all day.\" },\n              { \"title\": \"Shutdown ritual\", \"description\": \"Write tomorrow's top 3, then close the laptop.\" }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"type\": \"ending_slide\",\n      \"heading\": \"Start with one change\",\n      \"sub_heading\": \"You don't need a perfect setup\",\n      \"description\": \"Follow for more remote-work playbooks.\",\n      \"cta_button\": \"Follow\"\n    }\n  ]\n}\n\nFile v1.3.0:examples/import-video.json\n\n{\n  \"slides\": [\n    {\n      \"type\": \"starting_slide\",\n      \"heading\": \"3 habits of fast teams\",\n      \"sub_heading\": \"Remote work\",\n      \"description\": \"The ones that actually stick.\",\n      \"cta_button\": \"Watch on\",\n      \"background_image\": \"https://skfhtbmyanoeqbvrtxqa.supabase.co/storage/v1/object/public/media/static/postnitro-on-the-moon.png\"\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"Write things down\",\n      \"description\": \"Decisions live in docs, not in calls.\",\n      \"image\": \"https://skfhtbmyanoeqbvrtxqa.supabase.co/storage/v1/object/public/media/static/postnitro-on-the-moon.png\"\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"Default to async\",\n      \"description\": \"Protect deep work; meet only when it changes a decision.\",\n      \"layoutType\": \"infographic\",\n      \"layoutConfig\": {\n        \"hasHeader\": true,\n        \"columnCount\": 2,\n        \"displayCounterAs\": \"counter\",\n        \"columnDisplay\": \"grid\",\n        \"columnData\": [\n          {\n            \"id\": \"col-1\",\n            \"header\": \"Do\",\n            \"content\": [\n              {\n                \"id\": \"item-1\",\n                \"icon\": null,\n                \"title\": \"Write the update\",\n                \"description\": \"<p dir=\\\"ltr\\\">A doc beats a stand-up for anything not urgent.</p>\",\n                \"titleEnabled\": true,\n                \"descriptionEnabled\": true\n              },\n              {\n                \"id\": \"item-2\",\n                \"icon\": null,\n                \"title\": \"Batch replies\",\n                \"description\": \"<p dir=\\\"ltr\\\">Two windows a day, not two minutes an hour.</p>\",\n                \"titleEnabled\": true,\n                \"descriptionEnabled\": true\n              }\n            ]\n          },\n          {\n            \"id\": \"col-2\",\n            \"header\": \"Don't\",\n            \"content\": [\n              {\n                \"id\": \"item-3\",\n                \"icon\": null,\n                \"title\": \"Meet to decide\",\n                \"description\": \"<p dir=\\\"ltr\\\">Bring the decision to the meeting, not the debate.</p>\",\n                \"titleEnabled\": true,\n                \"descriptionEnabled\": true\n              },\n              {\n                \"id\": \"item-4\",\n                \"icon\": null,\n                \"title\": \"Ping for status\",\n                \"description\": \"<p dir=\\\"ltr\\\">If it's worth asking, it's worth writing down once.</p>\",\n                \"titleEnabled\": true,\n                \"descriptionEnabled\": true\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"type\": \"ending_slide\",\n      \"heading\": \"Try one this week\",\n      \"description\": \"Pick the habit your team misses most.\",\n      \"cta_button\": \"Follow for more\"\n    }\n  ]\n}\n\nFile v1.3.0:examples/schedule-post.json\n\n{\n  \"status\": \"SCHEDULED\",\n  \"scheduledAt\": \"2026-12-31T13:00:00Z\",\n  \"designId\": \"<designId from carousel generate/import --wait>\",\n  \"selectedAccounts\": [\"<socialAccountId>\"],\n  \"postContent\": {\n    \"common\": \"New carousel is live 🚀 Save this one for later. #remotework #productivity\"\n  },\n  \"linkedinPostSettings\": {\n    \"postType\": \"document\",\n    \"postTitle\": \"Remote Work, Done Right\"\n  }\n}\n\nArchive v1.2.1: 8 files, 16493 bytes\n\nFiles: examples/EXAMPLES.md (2451b), examples/import-default.json (917b), examples/import-infographics.json (2322b), examples/schedule-post.json (400b), references/cli-reference.md (12644b), skill-card.md (2696b), SKILL.md (18605b), _meta.json (128b)\n\nFile v1.2.1:SKILL.md\n\n---\nname: postnitro\ndescription: Create on-brand social media carousels and single-image posts and schedule them to LinkedIn, Instagram, TikTok, and Threads from a single command. Turn a topic, article, or X thread into a finished multi-slide post or image — or import your own content — then publish or draft it automatically. Fully scriptable (JSON in, JSON out), so an AI agent can run the entire create-to-schedule workflow. Use this skill whenever the user wants to create a carousel, image post, slide post, or multi-slide content, repurpose an article, blog post, or X thread into slides, or automate and schedule social media posts. Use it to create and schedule content through PostNitro, not as a general social-media strategy advisor. Requires a PostNitro API key.\nhomepage: https://postnitro.ai\nmetadata: {\"openclaw\":{\"emoji\":\"🎠\",\"primaryEnv\":\"POSTNITRO_API_KEY\",\"requires\":{\"bins\":[],\"env\":[\"POSTNITRO_API_KEY\"]}}}\n---\n\n# PostNitro — Create & Schedule Social Posts\n\nPostNitro creates on-brand social media posts — multi-slide carousels and single images — and schedules them across LinkedIn, Instagram, TikTok, and Threads. This skill drives it from the command line, so an agent can take a topic, article, or your own content and produce a finished, scheduled post in one workflow. Every command is JSON in / JSON out — safe to script and chain.\n\n## Setup\n\n1. Install the CLI:\n   ```bash\n   npm install -g @postnitro/cli\n   ```\n2. Sign up at https://postnitro.ai and subscribe to a plan — the Embed API requires a **paid subscription** (no free tier). Then generate an API key at account settings → **Embed** → Generate API Key.\n3. Authenticate (in order of precedence: `--api-key` flag → env var → saved config):\n   ```bash\n   postnitro auth set-key pn-xxxx        # persists to ~/.postnitro-cli/config.json\n   export POSTNITRO_API_KEY=\"pn-xxxx\"    # or use an env var\n   ```\n4. Save defaults so you don't repeat template/brand/preset IDs on every call (the CLI's alternative to per-call flags — no env vars needed):\n   ```bash\n   postnitro defaults set --template-id <id> --brand-id <id> --preset-id <id> --response-type PDF\n   ```\n\n| Env var | Required | Purpose |\n|---------|----------|---------|\n| `POSTNITRO_API_KEY` | Yes* | API key (*unless passed via `--api-key` or saved with `auth set-key`) |\n\n> **Key rule:** `carousel generate`/`import` return an **`embedPostId`** (the async job). To *schedule* the result you need its **`designId`** (from the `--wait` output or `carousel output`). Never pass an `embedPostId` to `schedule`.\n\n> **Security:** `auth set-key` stores your API key in plaintext at `~/.postnitro-cli/config.json`. Restrict its file permissions and avoid shared or untrusted machines; run `auth clear` to remove it. This skill runs **no background processes, cron jobs, or startup scripts** — the only local state is the API key and saved defaults, both disclosed above.\n\n> **When NOT to use:** as a general social-media strategy advisor when no content is being produced. *(PostNitro composes with other tools — e.g., create a carousel here, then schedule it elsewhere — so pairing it with another scheduler is fine.)*\n\n## Core Workflow\n\nEvery create command is asynchronous — `--wait` handles the polling and returns the finished output (including `designId` and `editorUrl`) in one call.\n\n### 1. Create a post\n\nTwo independent choices decide which command you run:\n\n- **Post type** — a multi-slide `carousel` or a single `image`.\n- **Content source** — let AI write it (`generate`) or supply your own (`import`).\n\nThat's four commands:\n\n| | `generate` (AI writes it) | `import` (you supply content) |\n|---|---|---|\n| **`carousel`** (multi-slide) | `postnitro carousel generate` | `postnitro carousel import` |\n| **`image`** (single) | `postnitro image generate` | `postnitro image import` |\n\nAll four take `--template-id`/`--brand-id` (from flags or saved defaults) plus the modifiers in step 2, and every result includes the **`designId`** (needed to schedule) and an **`editorUrl`**.\n\n#### AI-generated (`generate`)\n\n```bash\npostnitro carousel generate \\\n  --context \"5 tips for growing your LinkedIn audience in 2026\" \\\n  --type text \\\n  --instructions \"Professional tone, actionable advice\" \\\n  --wait\n\n# Single image instead — same flags, just the image subcommand\npostnitro image generate --context \"Announce our new scheduling feature\" --wait\n```\n\n**`--type` values:**\n- `text` — `--context` is the topic/text to turn into a post\n- `article` — `--context` is an article URL to extract and convert\n- `x` — `--context` is an X (Twitter) post/thread URL\n\n`generate` also needs an AI preset (`--preset-id`, or a saved default).\n\n#### Import your own content (`import`)\n\n```bash\n# Carousel — slides is an ARRAY of typed slides (inline --slides overrides --file)\npostnitro carousel import --slides '{\"slides\":[\n  {\"type\":\"starting_slide\",\"heading\":\"Your Title\",\"description\":\"Intro text\"},\n  {\"type\":\"body_slide\",\"heading\":\"Key Point\",\"description\":\"Details here\"},\n  {\"type\":\"ending_slide\",\"heading\":\"Take Action!\",\"cta_button\":\"Learn More\"}\n]}' --wait\npostnitro carousel import --file ./slides.json --wait\n\n# Single image — slide is a SINGLE OBJECT (not an array), via --slide\npostnitro image import --slide '{\"heading\":\"Welcome!\",\"sub_heading\":\"Subtitle\",\"cta_button\":\"Learn more\"}' --wait\n```\n\n- **Carousel** (`--slides`, array): exactly 1 `starting_slide` (first), ≥1 `body_slide`, exactly 1 `ending_slide` (last); `heading` required on every slide. Run `postnitro carousel import-template` for the schema. Ready-to-use: [examples/import-default.json](examples/import-default.json), [examples/import-infographics.json](examples/import-infographics.json).\n- **Image** (`--slide`, one object): fields `heading` (required), `sub_heading`, `description`, `cta_button`, `image`, `background_image` (plus infographic — see step 2). Sending an array here is rejected. Run `postnitro image import-template` for the schema.\n\n### 2. Options for any create command\n\nThese layer onto any of the four commands above (and onto `generate-and-schedule`).\n\n#### Output format — `--response-type PDF | PNG | DESIGN`\n\nDefault `PDF` (single file URL). `PNG` returns one URL per slide. `DESIGN` **skips rendering** — no file is produced; you get just the `designId` + `editorUrl`, the fastest option when you only need to schedule or edit.\n\n#### AI image generation — `--generate-images` (any post type, any source)\n\nOpt in to have AI generate images and bake them into the design before rendering. Works on **all four** create commands (and `generate-and-schedule`), for both carousels and images. Requires an `--image-context` brief:\n\n```bash\npostnitro carousel generate --context \"How scheduling saves marketers time\" \\\n  --generate-images --image-context \"upbeat and professional, product-focused\" \\\n  --image-placement auto --image-strategy all --wait\n```\n\n- `--image-context <text>` — **required** when generating images: a short visual brief for the image prompts\n- `--image-placement auto|background|in-line` (default `auto` — AI decides per slide)\n- `--image-strategy strategic|all` (`strategic` ≈ 50% of slides, default; `all` = every eligible slide)\n\n**Best-effort:** the post still completes if images fail or aren't permitted. With `--wait`, the result carries an `imageGeneration` field (the `GENERATE_IMAGES` step); if its `status` is `FAILED`, its `message` explains why (e.g. free plan can't generate AI images, or the org is over its AI-image quota). AI images bill against the org's **separate AI-image quota**, not the post's slide credits, and add latency. Without `--wait`, the same step shows up in `status` logs.\n\n#### Infographic layout — `import` only\n\nOn either `import` command, set `layoutType: \"infographic\"` on a slide (with a `layoutConfig`) to render data columns (max 3) instead of an image. Every column and content item needs a caller-provided `id`, and each item `description` is an HTML string. See `carousel import-template` / `image import-template` for the full schema.\n\n### 3. Check status / get output (only if you didn't use `--wait`)\n\n```bash\npostnitro carousel status <embedPostId>   # progress + step logs; poll until COMPLETED\npostnitro carousel output <embedPostId>   # final file URL(s) + designId + editorUrl\n```\n(`image status` / `image output` work identically for image posts.)\n\nOutput is a PDF (single URL) or PNG (one URL per slide) in `data`, plus the `designId` and `editorUrl`. Those can be handed to another tool — e.g. a different scheduler — to publish on platforms PostNitro doesn't cover. With `--response-type DESIGN` there's no rendered file, so `data`/`mimeType`/`outputType` are omitted (you still get `designId` and `editorUrl`).\n\n### 4. Schedule the design to social accounts\n\n```bash\npostnitro social list   # get account IDs + platforms\n\npostnitro schedule create \\\n  --status SCHEDULED \\\n  --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --design-id <designId> \\\n  --selected-accounts '[\"<socialAccountId>\"]' \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"5–90 char title\"}' \\\n  --post-content '{\"common\":\"Caption with #hashtags\"}'\n```\n\n### 5. One-shot: create + schedule\n\nCreate and schedule in a single call — `generate-and-schedule` (AI writes it) or `import-and-schedule` (your own content). Both accept the schedule flags from step 4, `--post-type CAROUSEL|IMAGE`, and the AI-image options from step 2. If creation succeeds but scheduling fails, the error returns the `designId` so you can retry `schedule create` without re-creating (or re-spending credits).\n\n```bash\n# AI-generated\npostnitro generate-and-schedule \\\n  --context \"topic\" --type text \\\n  --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --selected-accounts '[\"<socialAccountId>\"]' \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"...\"}' \\\n  --post-content '{\"common\":\"...\"}'\n\n# Your own content — --slides (carousel array) or --slide (single image); --slides-file for a file.\n# (Here --file is the SCHEDULE body, so slides come from --slides / --slides-file.)\npostnitro import-and-schedule \\\n  --slides '{\"slides\":[ ... ]}' \\\n  --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --selected-accounts '[\"<socialAccountId>\"]' \\\n  --post-content '{\"common\":\"...\"}'\n```\n\n## Common Patterns\n\n### Pattern 1: LinkedIn thought-leadership carousel\n```bash\npostnitro carousel generate \\\n  --context \"5 mistakes startups make with their LinkedIn strategy and how to fix each one\" \\\n  --type text --instructions \"Professional but conversational. One clear takeaway per slide.\" --wait\n```\n\n### Pattern 2: Repurpose a blog post\n```bash\npostnitro carousel generate --context \"https://yourblog.com/posts/social-media-strategy-2026\" \\\n  --type article --instructions \"Extract the 5 most actionable points. Keep slide text concise.\" --wait\n```\n\n### Pattern 3: Repurpose an X thread\n```bash\npostnitro carousel generate --context \"https://x.com/username/status/1234567890\" \\\n  --type x --instructions \"Maintain the original voice and key points\" --wait\n```\n\n### Pattern 4: Data-driven infographic carousel\nImport slides with `layoutType: \"infographic\"` body slides — see\n[examples/import-infographics.json](examples/import-infographics.json).\n\n### Pattern 5: Generate → schedule to LinkedIn\n```bash\nDID=$(postnitro carousel generate --context \"5 remote work habits\" --type text --wait | jq -r .designId)\nLINKEDIN=$(postnitro social list | jq -r 'first(.accounts[] | select(.platform==\"linkedin\").id)')\npostnitro schedule create --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --design-id \"$DID\" --selected-accounts \"[\\\"$LINKEDIN\\\"]\" \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"5 remote work habits\"}' \\\n  --post-content '{\"common\":\"New carousel 🚀 #remotework\"}'\n```\n\n### Pattern 6: Batch scheduling\n```bash\nDATES=(\"2026-02-14T09:00:00Z\" \"2026-02-15T09:00:00Z\")\nTOPICS=(\"Monday motivation 💪\" \"Tuesday tips 💡\")\nfor i in \"${!DATES[@]}\"; do\n  postnitro generate-and-schedule --context \"${TOPICS[$i]}\" --type text \\\n    --status SCHEDULED --scheduled-at \"${DATES[$i]}\" \\\n    --selected-accounts '[\"<socialAccountId>\"]' \\\n    --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"Daily post\"}'\ndone\n```\n\n## Content Strategy Tips\n\n- **LinkedIn**: professional tone, actionable insights, 6–10 slides, clear CTA. PDF carousels post as `postType: \"document\"` (needs a 5–90 char `postTitle`).\n- **Instagram**: visual-first, concise text, 5–8 slides, storytelling arc. `postAsStory` for stories.\n- **TikTok**: trendy, punchy, 4–7 slides, hook on slide 1.\n- **X / Threads**: data-driven, 3–6 slides, provocative opening.\n\n## Common Gotchas\n\n1. **Not authenticated** — run `postnitro auth status`; set a key before anything else.\n2. **Scheduling with `embedPostId`** — use the **`designId`** from `--wait`/`carousel output`, never the `embedPostId`.\n3. **`Scheduled at is in the past`** — `--scheduled-at` must be a future ISO-8601 datetime with a trailing `Z`.\n4. **Invalid inline JSON** — wrap JSON flags in single quotes; the CLI validates before any network call.\n5. **`Missing --brand-id ... multiple candidates`** — pass the ID or save a default with `defaults set`.\n6. **LinkedIn `document` rejected** — `postType:\"document\"` needs a 5–90 char `postTitle`.\n7. **Empty post** — a scheduled post needs either `--design-id` or non-empty `--post-content`.\n8. **Destructive commands** — `social disconnect` and `schedule delete` require `--yes`.\n9. **`SCHEDULED` publishes live** — use `DRAFT` when unsure; confirm time/account with the user first.\n10. **`responseType`** — the CLI defaults to `PDF` (pass `--response-type PNG` for individual slide images, or `DESIGN` to skip rendering and only create the design). Note: the underlying API now defaults to `DESIGN` when omitted, but the CLI always sends `PDF` explicitly, so CLI behavior is unchanged.\n11. **Credits vary** — AI generation ≈ 2 credits/slide; content import ≈ 1 credit/slide. Warn before large batches.\n\n## Credits & Pricing\n\nThe Embed API requires a **paid subscription** — there is no free tier, and free accounts cannot call the API. See **https://postnitro.ai/plans** for current plans and credit allowances.\n\nApproximate usage cost (observed):\n- Content import: ~1 credit per slide\n- AI generation: ~2 credits per slide\n\n## Supporting Resources\n\n**In this skill:**\n- [references/cli-reference.md](references/cli-reference.md) — complete command, platform-settings, and slide-schema reference\n- [examples/EXAMPLES.md](examples/EXAMPLES.md) — ready-to-use import & schedule JSON (`import-default.json`, `import-infographics.json`, `schedule-post.json`)\n\n**Full project docs (GitHub):**\n- [README](https://github.com/postnitro/postnitro-agent#readme) — full command reference\n- [QUICK_START.md](https://github.com/postnitro/postnitro-agent/blob/main/QUICK_START.md) — zero to a scheduled carousel in minutes\n- [HOW_TO_RUN.md](https://github.com/postnitro/postnitro-agent/blob/main/HOW_TO_RUN.md) — install & run methods\n- [PLATFORM_SETTINGS.md](https://github.com/postnitro/postnitro-agent/blob/main/PLATFORM_SETTINGS.md) — platform settings schemas\n- [FEATURES.md](https://github.com/postnitro/postnitro-agent/blob/main/FEATURES.md) — full feature list\n- Per-command help: `postnitro <command> <subcommand> --help`\n\n## Quick Reference\n\n```bash\n# Auth (do this first)\npostnitro auth set-key pn-xxxx | postnitro auth status | export POSTNITRO_API_KEY=pn-xxxx\n\n# Discover + defaults\npostnitro template list | brand list | preset list | social list\npostnitro defaults set --template-id <id> --brand-id <id> --preset-id <id> --response-type PDF\n\n# Create (async — use --wait; result has designId + editorUrl)\n# --response-type PDF|PNG|DESIGN (DESIGN skips rendering; CLI default is PDF)\n# Optional AI images (any generate/import): --generate-images --image-context \"brief\" [--image-placement auto|background|in-line] [--image-strategy strategic|all]\npostnitro carousel generate --context \"topic|url\" --type text|article|x [--instructions \"...\"] --wait\npostnitro carousel import (--slides '{\"slides\":[...]}' | --file ./slides.json) --wait\npostnitro carousel status <embedPostId>        # if not using --wait\npostnitro carousel output <embedPostId>        # file URLs + designId + editorUrl\n\n# Single-image posts (mirror carousel; import takes ONE slide object, not an array)\npostnitro image generate --context \"topic|url\" --type text|article|x --wait\npostnitro image import (--slide '{\"heading\":\"...\"}' | --file ./slide.json) --wait\n\n# Schedule (date REQUIRED + future; use designId, not embedPostId)\npostnitro schedule create --status SCHEDULED|DRAFT --scheduled-at \"<iso>\" --design-id <id> \\\n  --selected-accounts '[\"<id>\"]' --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"...\"}' \\\n  --post-content '{\"common\":\"caption\"}'\npostnitro schedule list --from \"<date>\" --to \"<date>\" | get <id> | delete <id> --yes\n\n# One-shot: create + schedule (both take --post-type + AI-image flags)\npostnitro generate-and-schedule --context \"topic\" --status SCHEDULED --scheduled-at \"<iso>\" ...\npostnitro import-and-schedule --slides '{\"slides\":[...]}' --status SCHEDULED --scheduled-at \"<iso>\" ...   # or --slide for image\n```\n\n## Tips for the Agent\n\n- Always confirm authentication (`postnitro auth status`) before running any other command. Never fabricate an API key — ask the user.\n- Prefer `--wait` so one call returns the finished output and `designId`.\n- Discover IDs with the `list` commands; save workspace defaults with `defaults set` so later calls stay short.\n- **Schedule with the `designId`, not the `embedPostId`.**\n- For `--type article`/`x`, `--context` must be a URL. For plain text, use `--type text`.\n- `responseType` defaults to PDF in the CLI — pass `--response-type PNG` for individual slide images, or `DESIGN` to skip rendering when you only need the `designId`/`editorUrl` (e.g. for scheduling).\n- `--scheduled-at` must be a **future** ISO-8601 datetime (trailing `Z`).\n- `status: SCHEDULED` creates a **live** post that will publish — confirm the time and account with the user, or use `DRAFT` when unsure.\n- Parse stdout as JSON; on failure read `.error.message` from stderr and fix the inputs.\n- Warn about credit costs before large batches (AI generation is ~2× the cost of import).\n- If the user doesn't specify a platform, suggest LinkedIn (most common carousel use case) and remember PDF carousels post there as `document`.\n\nFile v1.2.1:_meta.json\n\n{\n  \"ownerId\": \"kn75qwv6mp7qy963qgzggb2qrn815sm8\",\n  \"slug\": \"postnitro\",\n  \"version\": \"1.2.1\",\n  \"publishedAt\": 1784289417494\n}\n\nFile v1.2.1:references/cli-reference.md\n\n# PostNitro CLI — Command Reference\n\nComplete reference for `@postnitro/cli`. Every command prints JSON on stdout (exit 0) or a\n`{ \"success\": false, \"error\": { \"message\": ... } }` object on stderr (exit 1).\n\n## Global options\n\nAvailable on every command:\n\n| Flag | Purpose |\n|------|---------|\n| `--api-key <key>` | API key (overrides env/saved config) |\n| `-V, --version` | Print version |\n| `-h, --help` | Help for any command/subcommand |\n\n## auth\n\n```\npostnitro auth set-key <key>   # save to ~/.postnitro-cli/config.json\npostnitro auth status          # { configured, source, apiKey (masked) }\npostnitro auth clear           # remove saved key\n```\n\n> **Security:** `auth set-key` stores the API key in **plaintext** at `~/.postnitro-cli/config.json`. Restrict its file permissions (`chmod 600`), avoid shared or untrusted machines, and run `auth clear` to remove it. In CI, prefer `--api-key` or the `POSTNITRO_API_KEY` env var over the saved file.\n\n## defaults\n\n```\npostnitro defaults get\npostnitro defaults set [--template-id <id>] [--brand-id <id>] [--preset-id <id>] [--response-type PDF|PNG|DESIGN]\n```\nRequires at least one field. Resolution order per field: explicit flag → saved default → auto-select (when exactly one candidate exists).\n\n## template / brand / preset (discovery)\n\n```\npostnitro template list [--page <n>] [--limit <n>]\npostnitro preset list   [--page <n>] [--limit <n>]\npostnitro brand list    [--page <n>] [--limit <n>]\npostnitro brand get <id>\npostnitro brand create  (--name --handle --image [--company-detail] [--no-show-name|--no-show-handle|--no-show-image]) | --data <json> | --file <json>\npostnitro brand update <id> ...same as create...\n```\n`--data` (inline JSON object) overrides `--file`, which overrides the individual flags.\n\n## carousel\n\n```\npostnitro carousel import-template                 # prints the slide schema + rules\npostnitro carousel generate --context <text> [--type text|article|x] [--instructions <text>]\n                            [--template-id] [--brand-id] [--preset-id] [--response-type PDF|PNG|DESIGN]\n                            [--requestor-id <id>] [--wait]\npostnitro carousel import (--slides <json> | --file <path>)\n                          [--template-id] [--brand-id] [--response-type] [--requestor-id] [--wait]\npostnitro carousel status <embedPostId>            # progress + step logs\npostnitro carousel output <embedPostId>            # file URL(s) + designId + editorUrl\n```\n- `--type`: `text` (topic/text), `article` (article URL), `x` (X post URL).\n- `--response-type`: `PDF` (default) | `PNG` | `DESIGN`. `DESIGN` skips rendering — no file is produced, output has `designId` + `editorUrl` only.\n- `--wait`: poll to completion; returns final output incl. `designId` and `editorUrl`.\n- `--slides` (inline JSON) overrides `--file`; accepts a bare array or `{ \"slides\": [...] }`.\n- AI images: add `--generate-images` (+ optional `--image-placement`/`--image-strategy`/`--image-context`) — see [AI image generation](#ai-image-generation-generateimages).\n\n## image\n\nSingle-image posts. Mirrors `carousel`, but produces one image and `import` takes a **single slide object** (not an array).\n\n```\npostnitro image import-template                    # prints the image-slide schema + rules\npostnitro image generate --context <text> [--type text|article|x] [--instructions <text>]\n                         [--template-id] [--brand-id] [--preset-id] [--response-type PDF|PNG|DESIGN]\n                         [--requestor-id <id>] [--wait]\npostnitro image import (--slide <json> | --file <path>)\n                       [--template-id] [--brand-id] [--response-type] [--requestor-id] [--wait]\npostnitro image status <embedPostId>               # progress + step logs\npostnitro image output <embedPostId>               # file URL(s) + designId + editorUrl\n```\n- `--slide` (inline JSON) overrides `--file`; a **single object** (arrays are rejected — those are CAROUSEL-only). Accepts a bare object or `{ \"slides\": { ... } }`.\n- Allowed slide fields: `heading` (required), `sub_heading`, `description`, `cta_button`, `image`, `background_image`, plus `layoutType`/`layoutConfig` for the infographic layout. Any other field is rejected.\n- Infographic layout works on IMAGE too — set `layoutType: \"infographic\"` + `layoutConfig` (same schema as carousel; see below). Every column and content item needs a caller-provided `id`.\n- AI images: `--generate-images` (+ optional flags) works here too — see [AI image generation](#ai-image-generation-generateimages).\n\n## AI image generation (`generateImages`)\n\nOpt-in AI image generation, available on **every** generate/import command (carousel and image) and on `generate-and-schedule`. Images are generated and baked into the design before rendering, so they appear in the rendered file and in the editor.\n\n| Flag | Values | Default | Notes |\n|------|--------|---------|-------|\n| `--generate-images` | (boolean) | off | Opt in. Also implied by any flag below. |\n| `--image-context <text>` | string | — | **Required** when generating images: a short visual brief for the image prompts. |\n| `--image-placement <mode>` | `auto` \\| `background` \\| `in-line` | `auto` | `auto` = AI decides per slide. |\n| `--image-strategy <mode>` | `strategic` \\| `all` | `strategic` | `strategic` ≈ 50% of slides; `all` = every eligible slide. |\n\n- `--image-context` is required whenever image generation is enabled — the CLI fails fast if it's missing.\n- The two enums are validated client-side (fails fast on a bad value).\n- **Best-effort:** the post still completes if image generation fails or isn't permitted. With `--wait`, the result includes `imageGeneration` (the `GENERATE_IMAGES` job step); a `FAILED` status there (e.g. free plan, or over the org's AI-image quota) means the post completed without images. Without `--wait`, the step appears in `status` logs.\n- **Credits:** AI images consume the organization's **separate AI-image quota** — the post's slide-based `credits` are unchanged. Free plans cannot generate AI images.\n- Adds latency (real images are rendered); keep polling `status` until `COMPLETED`.\n\n## social\n\n```\npostnitro social list                 # { count, accounts: [{ id, platform, handle, name, accountType, status }] }\npostnitro social get <id>\npostnitro social disconnect <id> --yes # destructive\n```\n\n> **Destructive:** `social disconnect` removes the linked social account from your workspace. Scheduled posts targeting it will fail to publish, and restoring access requires reconnecting and re-authenticating. Requires `--yes`.\n\n## schedule\n\n```\npostnitro schedule list --from <date> --to <date>\npostnitro schedule create --status DRAFT|SCHEDULED --scheduled-at <iso>\n                          [--design-id <id>] [--file <json>]\n                          [--post-content <json>] [--selected-accounts <json>]\n                          [--instagram-post-settings <json>] [--tiktok-post-settings <json>]\n                          [--linkedin-post-settings <json>] [--threads-post-settings <json>]\n                          [--post-settings <json>]\npostnitro schedule get <id>\npostnitro schedule update <id> ...same flags as create...   # REPLACES state\npostnitro schedule delete <id> --yes\n```\n- **`schedule delete` is destructive:** it permanently cancels and removes the scheduled post — this cannot be undone. Requires `--yes`.\n- Requires either `--design-id` or non-empty `--post-content`.\n- `--scheduled-at` must be a **future** ISO-8601 datetime (trailing `Z`).\n- Inline JSON flags override the same field in `--file`.\n\n## generate-and-schedule\n\n```\npostnitro generate-and-schedule --context <text> --status DRAFT|SCHEDULED --scheduled-at <iso>\n                                [--post-type CAROUSEL|IMAGE] [ ...all generate flags... ]\n                                [--generate-images --image-context <text> ...]   # optional AI images\n                                [--design-id] [--file <json>]\n                                [--post-content] [--selected-accounts] [--*-post-settings] [--post-settings]\n```\nGenerates → waits → schedules in one call. `--post-type` defaults to `CAROUSEL` (use `IMAGE` for a single-image post). Also accepts the [AI image generation](#ai-image-generation-generateimages) flags. On scheduling failure the error includes the `designId` so you can retry `schedule create` without regenerating.\n\n## import-and-schedule\n\n```\npostnitro import-and-schedule --status DRAFT|SCHEDULED --scheduled-at <iso>\n                              [--post-type CAROUSEL|IMAGE]\n                              (--slides <json> | --slide <json> | --slides-file <path>)\n                              [--template-id] [--brand-id] [--response-type] [--requestor-id]\n                              [--generate-images --image-context <text> ...]   # optional AI images\n                              [--design-id] [--file <json>]\n                              [--post-content] [--selected-accounts] [--*-post-settings] [--post-settings]\n```\nImports your own content → waits → schedules in one call (the import-side counterpart of `generate-and-schedule`). `--post-type` defaults to `CAROUSEL` — pass `--slides` (array) for CAROUSEL or `--slide` (single object) for IMAGE; `--slides-file` reads either from a file.\n\n> **Flag note:** here `--file` is the **schedule body** (postContent/accounts/settings), matching `generate-and-schedule` — so slide content comes from `--slides` / `--slide` / `--slides-file`, not `--file`.\n\nAlso accepts the [AI image generation](#ai-image-generation-generateimages) flags. On scheduling failure the error includes the `designId` so you can retry `schedule create` without re-importing.\n\n---\n\n## Captions — `postContent`\n\nJSON object keyed by platform. At least one non-empty caption unless `--design-id` is set. Hashtags auto-extracted.\nKeys: `common`, `linkedin`, `instagram`, `tiktok`, `facebook`, `threads`.\n\n## Platform settings\n\n| Flag | Shape |\n|------|-------|\n| `--linkedin-post-settings` | `{\"postType\":\"carousel\\|document\\|image\\|reel\",\"postTitle\":\"...\"}` — `document` needs 5–90 char `postTitle` |\n| `--instagram-post-settings` | `{\"postType\":\"carousel\\|image\\|reel\",\"postAsStory\":false}` |\n| `--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}` |\n| `--threads-post-settings` | `{\"postType\":\"carousel\\|image\\|reel\"}` |\n| `--post-settings` (reel) | `{\"videoDuration\":30,\"audioId\":\"...\"}` |\n\n## Slide schema (import)\n\nFor **carousel** import: exactly one `starting_slide` (first), ≥1 `body_slide`, exactly one `ending_slide` (last). For **image** import it's a single object with no `type` field (see the `image` section above).\n\n| Field | Notes |\n|-------|-------|\n| `type` | `starting_slide` \\| `body_slide` \\| `ending_slide` (required) |\n| `heading` | required on every slide |\n| `sub_heading` | optional |\n| `description` | optional body text |\n| `image` | optional image URL (public); ignored if `layoutType: \"infographic\"` |\n| `background_image` | optional background URL |\n| `cta_button` | optional CTA text |\n| `layoutType` | `default` \\| `infographic` |\n| `layoutConfig` | required when `layoutType: \"infographic\"` |\n\nInfographic `layoutConfig` (works on both carousel and image slides):\n```json\n{\n  \"hasHeader\": true,\n  \"columnCount\": 1,\n  \"displayCounterAs\": \"counter\",  // \"counter\" (default) | \"none\"\n  \"columnDisplay\": \"grid\",        // \"grid\" (comparative, default) or \"cycle\" (sequential; data in FIRST column only)\n  \"columnData\": [\n    {\n      \"id\": \"col-1\",\n      \"header\": \"Column\",\n      \"content\": [\n        {\n          \"id\": \"item-1\",\n          \"icon\": null,\n          \"title\": \"Item\",\n          \"description\": \"<p dir=\\\"ltr\\\">HTML string</p>\",\n          \"titleEnabled\": true,\n          \"descriptionEnabled\": true\n        }\n      ]\n    }\n  ]\n}\n```\nMax 3 columns. Setting `layoutType: \"infographic\"` replaces the slide's `image`. **Every column and content item needs a caller-provided `id`** — the API does not auto-generate them. `description` is an HTML string. Omitted `layoutConfig` fields use the defaults above; if `layoutType` is `infographic` but `layoutConfig` is missing, the slide falls back to the default layout.\n\n## Environment variables\n\n| Variable | Default | Purpose |\n|----------|---------|---------|\n| `POSTNITRO_API_KEY` | – | API key |\n| `POSTNITRO_CONFIG_DIR` | `~/.postnitro-cli` | Config/defaults location |\n\nFile v1.2.1:examples/EXAMPLES.md\n\n# PostNitro CLI — Skill Examples\n\nReady-to-use files for the `postnitro` skill. Authenticate first\n(`postnitro auth set-key pn-...` or `export POSTNITRO_API_KEY=pn-...`).\n\n## Files\n\n| File | What it is | Use with |\n|------|------------|----------|\n| [import-default.json](import-default.json) | Basic 4-slide import (starting / body / body / ending) | `carousel import` |\n| [import-infographics.json](import-infographics.json) | Import with `grid` and `cycle` infographic body slides | `carousel import` |\n| [schedule-post.json](schedule-post.json) | A full `schedule` body (designId + accounts + caption + LinkedIn settings) | `schedule create --file` |\n\n## Import a carousel\n\n```bash\n# From a file\npostnitro carousel import --file examples/import-default.json --wait\n\n# With infographic slides\npostnitro carousel import --file examples/import-infographics.json --wait\n\n# Same JSON inline (overrides --file)\npostnitro carousel import --slides \"$(cat examples/import-default.json)\" --wait\n```\n\n## Generate with AI (no JSON file needed — flags only)\n\n```bash\npostnitro carousel generate --context \"5 LinkedIn growth tips\" --type text --wait\npostnitro carousel generate --context \"https://yourblog.com/post\" --type article --wait\npostnitro carousel generate --context \"https://x.com/user/status/123\" --type x --wait\n```\n\n## Schedule a finished design\n\nEdit `schedule-post.json` (set a real `designId` from the import/generate output and a real\n`socialAccountId` from `postnitro social list`), then:\n\n```bash\npostnitro schedule create --file examples/schedule-post.json\n```\n\nInline flags override any field in the file, e.g. change the time without editing the file:\n\n```bash\npostnitro schedule create --file examples/schedule-post.json --scheduled-at \"2027-01-15T09:00:00Z\"\n```\n\n## End-to-end (capture designId → schedule)\n\n```bash\nDID=$(postnitro carousel import --file examples/import-infographics.json --wait | jq -r .designId)\nLINKEDIN=$(postnitro social list | jq -r 'first(.accounts[] | select(.platform==\"linkedin\").id)')\npostnitro schedule create --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --design-id \"$DID\" --selected-accounts \"[\\\"$LINKEDIN\\\"]\" \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"Remote Work, Done Right\"}' \\\n  --post-content '{\"common\":\"New carousel 🚀 #remotework\"}'\n```\n\nSee [../references/cli-reference.md](../references/cli-reference.md) for the full command and schema reference.\n\nFile v1.2.1:skill-card.md\n\n## Description: <br>\nCreate on-brand social media carousels and single-image posts and schedule them to LinkedIn, Instagram, TikTok, and Threads from a single command. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[iammuneeb](https://clawhub.ai/user/iammuneeb) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users, marketers, and developers use PostNitro to create, import, and schedule branded carousel or single-image social posts through a scriptable CLI workflow. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill uses PostNitro credentials and publishing permissions to create or schedule social posts. <br>\nMitigation: Install it only for intended PostNitro publishing workflows, prefer an environment variable or per-command API key on shared machines, and clear saved credentials when they are no longer needed. <br>\nRisk: A SCHEDULED post can publish live to selected social accounts. <br>\nMitigation: Confirm the target account and scheduled time before using SCHEDULED, and use DRAFT when the publishing details are uncertain. <br>\nRisk: Delete and disconnect commands can cancel scheduled posts or affect linked social accounts. <br>\nMitigation: Use destructive commands only with explicit confirmation and review the selected schedule or social account before passing --yes. <br>\nRisk: Large batches or AI image generation can consume paid PostNitro credits. <br>\nMitigation: Warn users before large batch runs or AI image generation and verify that the account has the required subscription and quota. <br>\n\n\n## Reference(s): <br>\n- [PostNitro CLI command reference](references/cli-reference.md) <br>\n- [PostNitro skill examples](examples/EXAMPLES.md) <br>\n- [PostNitro homepage](https://postnitro.ai) <br>\n- [ClawHub skill page](https://clawhub.ai/iammuneeb/skills/postnitro) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, shell commands, configuration, JSON, guidance] <br>\n**Output Format:** [Markdown guidance with shell commands and JSON examples] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Commands emit JSON output and can create drafts, schedule posts, or manage linked social accounts when executed with valid PostNitro credentials.] <br>\n\n## Skill Version(s): <br>\n1.2.1 (source: server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v1.2.1:examples/import-default.json\n\n{\n  \"slides\": [\n    {\n      \"type\": \"starting_slide\",\n      \"heading\": \"5 LinkedIn Growth Tips\",\n      \"sub_heading\": \"For founders and creators\",\n      \"description\": \"Simple habits that compound into real reach.\",\n      \"cta_button\": \"Swipe →\"\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"Post when your audience is awake\",\n      \"description\": \"Check your analytics for peak hours and schedule around them, not around when you happen to be free.\"\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"Hook in the first line\",\n      \"description\": \"The first sentence decides whether anyone reads the rest. Lead with the payoff, not the setup.\"\n    },\n    {\n      \"type\": \"ending_slide\",\n      \"heading\": \"Pick one and start today\",\n      \"sub_heading\": \"Consistency beats intensity\",\n      \"description\": \"Follow for more practical growth playbooks.\",\n      \"cta_button\": \"Follow\"\n    }\n  ]\n}\n\nFile v1.2.1:examples/import-infographics.json\n\n{\n  \"slides\": [\n    {\n      \"type\": \"starting_slide\",\n      \"heading\": \"Remote Work, Done Right\",\n      \"sub_heading\": \"A 2-minute field guide\",\n      \"description\": \"The setup and habits that separate good remote workers from great ones.\",\n      \"cta_button\": \"Swipe →\"\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"The 4 pillars of a solid setup\",\n      \"description\": \"Get these right and everything else gets easier.\",\n      \"layoutType\": \"infographic\",\n      \"layoutConfig\": {\n        \"columnCount\": 2,\n        \"columnDisplay\": \"grid\",\n        \"displayCounterAs\": \"none\",\n        \"hasHeader\": true,\n        \"columnData\": [\n          {\n            \"header\": \"Space & Focus\",\n            \"content\": [\n              { \"title\": \"Dedicated Desk\", \"description\": \"A fixed spot signals to your brain that it's work time.\" },\n              { \"title\": \"Noise Control\", \"description\": \"Headphones or a closed door — pick one.\" }\n            ]\n          },\n          {\n            \"header\": \"Rhythm & Recovery\",\n            \"content\": [\n              { \"title\": \"Hard Stop Time\", \"description\": \"Set an end time and honor it.\" },\n              { \"title\": \"Lunch Away\", \"description\": \"Take 30 screen-free minutes.\" }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"A simple daily cadence\",\n      \"description\": \"Run your day in sequence, not in chaos.\",\n      \"layoutType\": \"infographic\",\n      \"layoutConfig\": {\n        \"columnCount\": 1,\n        \"columnDisplay\": \"cycle\",\n        \"displayCounterAs\": \"counter\",\n        \"hasHeader\": false,\n        \"columnData\": [\n          {\n            \"header\": \"Daily Flow\",\n            \"content\": [\n              { \"title\": \"Deep work first\", \"description\": \"90 minutes on the hardest task before any meetings.\" },\n              { \"title\": \"Batch comms\", \"description\": \"Two windows for Slack/email — not all day.\" },\n              { \"title\": \"Shutdown ritual\", \"description\": \"Write tomorrow's top 3, then close the laptop.\" }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"type\": \"ending_slide\",\n      \"heading\": \"Start with one change\",\n      \"sub_heading\": \"You don't need a perfect setup\",\n      \"description\": \"Follow for more remote-work playbooks.\",\n      \"cta_button\": \"Follow\"\n    }\n  ]\n}\n\nFile v1.2.1:examples/schedule-post.json\n\n{\n  \"status\": \"SCHEDULED\",\n  \"scheduledAt\": \"2026-12-31T13:00:00Z\",\n  \"designId\": \"<designId from carousel generate/import --wait>\",\n  \"selectedAccounts\": [\"<socialAccountId>\"],\n  \"postContent\": {\n    \"common\": \"New carousel is live 🚀 Save this one for later. #remotework #productivity\"\n  },\n  \"linkedinPostSettings\": {\n    \"postType\": \"document\",\n    \"postTitle\": \"Remote Work, Done Right\"\n  }\n}\n\nArchive v1.2.0: 8 files, 16501 bytes\n\nFiles: examples/EXAMPLES.md (2451b), examples/import-default.json (917b), examples/import-infographics.json (2322b), examples/schedule-post.json (400b), references/cli-reference.md (12644b), skill-card.md (2574b), SKILL.md (18605b), _meta.json (128b)\n\nFile v1.2.0:SKILL.md\n\n---\nname: postnitro\ndescription: Create on-brand social media carousels and single-image posts and schedule them to LinkedIn, Instagram, TikTok, and Threads from a single command. Turn a topic, article, or X thread into a finished multi-slide post or image — or import your own content — then publish or draft it automatically. Fully scriptable (JSON in, JSON out), so an AI agent can run the entire create-to-schedule workflow. Use this skill whenever the user wants to create a carousel, image post, slide post, or multi-slide content, repurpose an article, blog post, or X thread into slides, or automate and schedule social media posts. Use it to create and schedule content through PostNitro, not as a general social-media strategy advisor. Requires a PostNitro API key.\nhomepage: https://postnitro.ai\nmetadata: {\"openclaw\":{\"emoji\":\"🎠\",\"primaryEnv\":\"POSTNITRO_API_KEY\",\"requires\":{\"bins\":[],\"env\":[\"POSTNITRO_API_KEY\"]}}}\n---\n\n# PostNitro — Create & Schedule Social Posts\n\nPostNitro creates on-brand social media posts — multi-slide carousels and single images — and schedules them across LinkedIn, Instagram, TikTok, and Threads. This skill drives it from the command line, so an agent can take a topic, article, or your own content and produce a finished, scheduled post in one workflow. Every command is JSON in / JSON out — safe to script and chain.\n\n## Setup\n\n1. Install the CLI:\n   ```bash\n   npm install -g @postnitro/cli\n   ```\n2. Sign up at https://postnitro.ai and subscribe to a plan — the Embed API requires a **paid subscription** (no free tier). Then generate an API key at account settings → **Embed** → Generate API Key.\n3. Authenticate (in order of precedence: `--api-key` flag → env var → saved config):\n   ```bash\n   postnitro auth set-key pn-xxxx        # persists to ~/.postnitro-cli/config.json\n   export POSTNITRO_API_KEY=\"pn-xxxx\"    # or use an env var\n   ```\n4. Save defaults so you don't repeat template/brand/preset IDs on every call (the CLI's alternative to per-call flags — no env vars needed):\n   ```bash\n   postnitro defaults set --template-id <id> --brand-id <id> --preset-id <id> --response-type PDF\n   ```\n\n| Env var | Required | Purpose |\n|---------|----------|---------|\n| `POSTNITRO_API_KEY` | Yes* | API key (*unless passed via `--api-key` or saved with `auth set-key`) |\n\n> **Key rule:** `carousel generate`/`import` return an **`embedPostId`** (the async job). To *schedule* the result you need its **`designId`** (from the `--wait` output or `carousel output`). Never pass an `embedPostId` to `schedule`.\n\n> **Security:** `auth set-key` stores your API key in plaintext at `~/.postnitro-cli/config.json`. Restrict its file permissions and avoid shared or untrusted machines; run `auth clear` to remove it. This skill runs **no background processes, cron jobs, or startup scripts** — the only local state is the API key and saved defaults, both disclosed above.\n\n> **When NOT to use:** as a general social-media strategy advisor when no content is being produced. *(PostNitro composes with other tools — e.g., create a carousel here, then schedule it elsewhere — so pairing it with another scheduler is fine.)*\n\n## Core Workflow\n\nEvery create command is asynchronous — `--wait` handles the polling and returns the finished output (including `designId` and `editorUrl`) in one call.\n\n### 1. Create a post\n\nTwo independent choices decide which command you run:\n\n- **Post type** — a multi-slide `carousel` or a single `image`.\n- **Content source** — let AI write it (`generate`) or supply your own (`import`).\n\nThat's four commands:\n\n| | `generate` (AI writes it) | `import` (you supply content) |\n|---|---|---|\n| **`carousel`** (multi-slide) | `postnitro carousel generate` | `postnitro carousel import` |\n| **`image`** (single) | `postnitro image generate` | `postnitro image import` |\n\nAll four take `--template-id`/`--brand-id` (from flags or saved defaults) plus the modifiers in step 2, and every result includes the **`designId`** (needed to schedule) and an **`editorUrl`**.\n\n#### AI-generated (`generate`)\n\n```bash\npostnitro carousel generate \\\n  --context \"5 tips for growing your LinkedIn audience in 2026\" \\\n  --type text \\\n  --instructions \"Professional tone, actionable advice\" \\\n  --wait\n\n# Single image instead — same flags, just the image subcommand\npostnitro image generate --context \"Announce our new scheduling feature\" --wait\n```\n\n**`--type` values:**\n- `text` — `--context` is the topic/text to turn into a post\n- `article` — `--context` is an article URL to extract and convert\n- `x` — `--context` is an X (Twitter) post/thread URL\n\n`generate` also needs an AI preset (`--preset-id`, or a saved default).\n\n#### Import your own content (`import`)\n\n```bash\n# Carousel — slides is an ARRAY of typed slides (inline --slides overrides --file)\npostnitro carousel import --slides '{\"slides\":[\n  {\"type\":\"starting_slide\",\"heading\":\"Your Title\",\"description\":\"Intro text\"},\n  {\"type\":\"body_slide\",\"heading\":\"Key Point\",\"description\":\"Details here\"},\n  {\"type\":\"ending_slide\",\"heading\":\"Take Action!\",\"cta_button\":\"Learn More\"}\n]}' --wait\npostnitro carousel import --file ./slides.json --wait\n\n# Single image — slide is a SINGLE OBJECT (not an array), via --slide\npostnitro image import --slide '{\"heading\":\"Welcome!\",\"sub_heading\":\"Subtitle\",\"cta_button\":\"Learn more\"}' --wait\n```\n\n- **Carousel** (`--slides`, array): exactly 1 `starting_slide` (first), ≥1 `body_slide`, exactly 1 `ending_slide` (last); `heading` required on every slide. Run `postnitro carousel import-template` for the schema. Ready-to-use: [examples/import-default.json](examples/import-default.json), [examples/import-infographics.json](examples/import-infographics.json).\n- **Image** (`--slide`, one object): fields `heading` (required), `sub_heading`, `description`, `cta_button`, `image`, `background_image` (plus infographic — see step 2). Sending an array here is rejected. Run `postnitro image import-template` for the schema.\n\n### 2. Options for any create command\n\nThese layer onto any of the four commands above (and onto `generate-and-schedule`).\n\n#### Output format — `--response-type PDF | PNG | DESIGN`\n\nDefault `PDF` (single file URL). `PNG` returns one URL per slide. `DESIGN` **skips rendering** — no file is produced; you get just the `designId` + `editorUrl`, the fastest option when you only need to schedule or edit.\n\n#### AI image generation — `--generate-images` (any post type, any source)\n\nOpt in to have AI generate images and bake them into the design before rendering. Works on **all four** create commands (and `generate-and-schedule`), for both carousels and images. Requires an `--image-context` brief:\n\n```bash\npostnitro carousel generate --context \"How scheduling saves marketers time\" \\\n  --generate-images --image-context \"upbeat and professional, product-focused\" \\\n  --image-placement auto --image-strategy all --wait\n```\n\n- `--image-context <text>` — **required** when generating images: a short visual brief for the image prompts\n- `--image-placement auto|background|in-line` (default `auto` — AI decides per slide)\n- `--image-strategy strategic|all` (`strategic` ≈ 50% of slides, default; `all` = every eligible slide)\n\n**Best-effort:** the post still completes if images fail or aren't permitted. With `--wait`, the result carries an `imageGeneration` field (the `GENERATE_IMAGES` step); if its `status` is `FAILED`, its `message` explains why (e.g. free plan can't generate AI images, or the org is over its AI-image quota). AI images bill against the org's **separate AI-image quota**, not the post's slide credits, and add latency. Without `--wait`, the same step shows up in `status` logs.\n\n#### Infographic layout — `import` only\n\nOn either `import` command, set `layoutType: \"infographic\"` on a slide (with a `layoutConfig`) to render data columns (max 3) instead of an image. Every column and content item needs a caller-provided `id`, and each item `description` is an HTML string. See `carousel import-template` / `image import-template` for the full schema.\n\n### 3. Check status / get output (only if you didn't use `--wait`)\n\n```bash\npostnitro carousel status <embedPostId>   # progress + step logs; poll until COMPLETED\npostnitro carousel output <embedPostId>   # final file URL(s) + designId + editorUrl\n```\n(`image status` / `image output` work identically for image posts.)\n\nOutput is a PDF (single URL) or PNG (one URL per slide) in `data`, plus the `designId` and `editorUrl`. Those can be handed to another tool — e.g. a different scheduler — to publish on platforms PostNitro doesn't cover. With `--response-type DESIGN` there's no rendered file, so `data`/`mimeType`/`outputType` are omitted (you still get `designId` and `editorUrl`).\n\n### 4. Schedule the design to social accounts\n\n```bash\npostnitro social list   # get account IDs + platforms\n\npostnitro schedule create \\\n  --status SCHEDULED \\\n  --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --design-id <designId> \\\n  --selected-accounts '[\"<socialAccountId>\"]' \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"5–90 char title\"}' \\\n  --post-content '{\"common\":\"Caption with #hashtags\"}'\n```\n\n### 5. One-shot: create + schedule\n\nCreate and schedule in a single call — `generate-and-schedule` (AI writes it) or `import-and-schedule` (your own content). Both accept the schedule flags from step 4, `--post-type CAROUSEL|IMAGE`, and the AI-image options from step 2. If creation succeeds but scheduling fails, the error returns the `designId` so you can retry `schedule create` without re-creating (or re-spending credits).\n\n```bash\n# AI-generated\npostnitro generate-and-schedule \\\n  --context \"topic\" --type text \\\n  --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --selected-accounts '[\"<socialAccountId>\"]' \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"...\"}' \\\n  --post-content '{\"common\":\"...\"}'\n\n# Your own content — --slides (carousel array) or --slide (single image); --slides-file for a file.\n# (Here --file is the SCHEDULE body, so slides come from --slides / --slides-file.)\npostnitro import-and-schedule \\\n  --slides '{\"slides\":[ ... ]}' \\\n  --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --selected-accounts '[\"<socialAccountId>\"]' \\\n  --post-content '{\"common\":\"...\"}'\n```\n\n## Common Patterns\n\n### Pattern 1: LinkedIn thought-leadership carousel\n```bash\npostnitro carousel generate \\\n  --context \"5 mistakes startups make with their LinkedIn strategy and how to fix each one\" \\\n  --type text --instructions \"Professional but conversational. One clear takeaway per slide.\" --wait\n```\n\n### Pattern 2: Repurpose a blog post\n```bash\npostnitro carousel generate --context \"https://yourblog.com/posts/social-media-strategy-2026\" \\\n  --type article --instructions \"Extract the 5 most actionable points. Keep slide text concise.\" --wait\n```\n\n### Pattern 3: Repurpose an X thread\n```bash\npostnitro carousel generate --context \"https://x.com/username/status/1234567890\" \\\n  --type x --instructions \"Maintain the original voice and key points\" --wait\n```\n\n### Pattern 4: Data-driven infographic carousel\nImport slides with `layoutType: \"infographic\"` body slides — see\n[examples/import-infographics.json](examples/import-infographics.json).\n\n### Pattern 5: Generate → schedule to LinkedIn\n```bash\nDID=$(postnitro carousel generate --context \"5 remote work habits\" --type text --wait | jq -r .designId)\nLINKEDIN=$(postnitro social list | jq -r 'first(.accounts[] | select(.platform==\"linkedin\").id)')\npostnitro schedule create --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --design-id \"$DID\" --selected-accounts \"[\\\"$LINKEDIN\\\"]\" \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"5 remote work habits\"}' \\\n  --post-content '{\"common\":\"New carousel 🚀 #remotework\"}'\n```\n\n### Pattern 6: Batch scheduling\n```bash\nDATES=(\"2026-02-14T09:00:00Z\" \"2026-02-15T09:00:00Z\")\nTOPICS=(\"Monday motivation 💪\" \"Tuesday tips 💡\")\nfor i in \"${!DATES[@]}\"; do\n  postnitro generate-and-schedule --context \"${TOPICS[$i]}\" --type text \\\n    --status SCHEDULED --scheduled-at \"${DATES[$i]}\" \\\n    --selected-accounts '[\"<socialAccountId>\"]' \\\n    --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"Daily post\"}'\ndone\n```\n\n## Content Strategy Tips\n\n- **LinkedIn**: professional tone, actionable insights, 6–10 slides, clear CTA. PDF carousels post as `postType: \"document\"` (needs a 5–90 char `postTitle`).\n- **Instagram**: visual-first, concise text, 5–8 slides, storytelling arc. `postAsStory` for stories.\n- **TikTok**: trendy, punchy, 4–7 slides, hook on slide 1.\n- **X / Threads**: data-driven, 3–6 slides, provocative opening.\n\n## Common Gotchas\n\n1. **Not authenticated** — run `postnitro auth status`; set a key before anything else.\n2. **Scheduling with `embedPostId`** — use the **`designId`** from `--wait`/`carousel output`, never the `embedPostId`.\n3. **`Scheduled at is in the past`** — `--scheduled-at` must be a future ISO-8601 datetime with a trailing `Z`.\n4. **Invalid inline JSON** — wrap JSON flags in single quotes; the CLI validates before any network call.\n5. **`Missing --brand-id ... multiple candidates`** — pass the ID or save a default with `defaults set`.\n6. **LinkedIn `document` rejected** — `postType:\"document\"` needs a 5–90 char `postTitle`.\n7. **Empty post** — a scheduled post needs either `--design-id` or non-empty `--post-content`.\n8. **Destructive commands** — `social disconnect` and `schedule delete` require `--yes`.\n9. **`SCHEDULED` publishes live** — use `DRAFT` when unsure; confirm time/account with the user first.\n10. **`responseType`** — the CLI defaults to `PDF` (pass `--response-type PNG` for individual slide images, or `DESIGN` to skip rendering and only create the design). Note: the underlying API now defaults to `DESIGN` when omitted, but the CLI always sends `PDF` explicitly, so CLI behavior is unchanged.\n11. **Credits vary** — AI generation ≈ 2 credits/slide; content import ≈ 1 credit/slide. Warn before large batches.\n\n## Credits & Pricing\n\nThe Embed API requires a **paid subscription** — there is no free tier, and free accounts cannot call the API. See **https://postnitro.ai/plans** for current plans and credit allowances.\n\nApproximate usage cost (observed):\n- Content import: ~1 credit per slide\n- AI generation: ~2 credits per slide\n\n## Supporting Resources\n\n**In this skill:**\n- [references/cli-reference.md](references/cli-reference.md) — complete command, platform-settings, and slide-schema reference\n- [examples/EXAMPLES.md](examples/EXAMPLES.md) — ready-to-use import & schedule JSON (`import-default.json`, `import-infographics.json`, `schedule-post.json`)\n\n**Full project docs (GitHub):**\n- [README](https://github.com/postnitro/postnitro-agent#readme) — full command reference\n- [QUICK_START.md](https://github.com/postnitro/postnitro-agent/blob/main/QUICK_START.md) — zero to a scheduled carousel in minutes\n- [HOW_TO_RUN.md](https://github.com/postnitro/postnitro-agent/blob/main/HOW_TO_RUN.md) — install & run methods\n- [PLATFORM_SETTINGS.md](https://github.com/postnitro/postnitro-agent/blob/main/PLATFORM_SETTINGS.md) — platform settings schemas\n- [FEATURES.md](https://github.com/postnitro/postnitro-agent/blob/main/FEATURES.md) — full feature list\n- Per-command help: `postnitro <command> <subcommand> --help`\n\n## Quick Reference\n\n```bash\n# Auth (do this first)\npostnitro auth set-key pn-xxxx | postnitro auth status | export POSTNITRO_API_KEY=pn-xxxx\n\n# Discover + defaults\npostnitro template list | brand list | preset list | social list\npostnitro defaults set --template-id <id> --brand-id <id> --preset-id <id> --response-type PDF\n\n# Create (async — use --wait; result has designId + editorUrl)\n# --response-type PDF|PNG|DESIGN (DESIGN skips rendering; CLI default is PDF)\n# Optional AI images (any generate/import): --generate-images --image-context \"brief\" [--image-placement auto|background|in-line] [--image-strategy strategic|all]\npostnitro carousel generate --context \"topic|url\" --type text|article|x [--instructions \"...\"] --wait\npostnitro carousel import (--slides '{\"slides\":[...]}' | --file ./slides.json) --wait\npostnitro carousel status <embedPostId>        # if not using --wait\npostnitro carousel output <embedPostId>        # file URLs + designId + editorUrl\n\n# Single-image posts (mirror carousel; import takes ONE slide object, not an array)\npostnitro image generate --context \"topic|url\" --type text|article|x --wait\npostnitro image import (--slide '{\"heading\":\"...\"}' | --file ./slide.json) --wait\n\n# Schedule (date REQUIRED + future; use designId, not embedPostId)\npostnitro schedule create --status SCHEDULED|DRAFT --scheduled-at \"<iso>\" --design-id <id> \\\n  --selected-accounts '[\"<id>\"]' --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"...\"}' \\\n  --post-content '{\"common\":\"caption\"}'\npostnitro schedule list --from \"<date>\" --to \"<date>\" | get <id> | delete <id> --yes\n\n# One-shot: create + schedule (both take --post-type + AI-image flags)\npostnitro generate-and-schedule --context \"topic\" --status SCHEDULED --scheduled-at \"<iso>\" ...\npostnitro import-and-schedule --slides '{\"slides\":[...]}' --status SCHEDULED --scheduled-at \"<iso>\" ...   # or --slide for image\n```\n\n## Tips for the Agent\n\n- Always confirm authentication (`postnitro auth status`) before running any other command. Never fabricate an API key — ask the user.\n- Prefer `--wait` so one call returns the finished output and `designId`.\n- Discover IDs with the `list` commands; save workspace defaults with `defaults set` so later calls stay short.\n- **Schedule with the `designId`, not the `embedPostId`.**\n- For `--type article`/`x`, `--context` must be a URL. For plain text, use `--type text`.\n- `responseType` defaults to PDF in the CLI — pass `--response-type PNG` for individual slide images, or `DESIGN` to skip rendering when you only need the `designId`/`editorUrl` (e.g. for scheduling).\n- `--scheduled-at` must be a **future** ISO-8601 datetime (trailing `Z`).\n- `status: SCHEDULED` creates a **live** post that will publish — confirm the time and account with the user, or use `DRAFT` when unsure.\n- Parse stdout as JSON; on failure read `.error.message` from stderr and fix the inputs.\n- Warn about credit costs before large batches (AI generation is ~2× the cost of import).\n- If the user doesn't specify a platform, suggest LinkedIn (most common carousel use case) and remember PDF carousels post there as `document`.\n\nFile v1.2.0:_meta.json\n\n{\n  \"ownerId\": \"kn75qwv6mp7qy963qgzggb2qrn815sm8\",\n  \"slug\": \"postnitro\",\n  \"version\": \"1.2.0\",\n  \"publishedAt\": 1784288847838\n}\n\nFile v1.2.0:references/cli-reference.md\n\n# PostNitro CLI — Command Reference\n\nComplete reference for `@postnitro/cli`. Every command prints JSON on stdout (exit 0) or a\n`{ \"success\": false, \"error\": { \"message\": ... } }` object on stderr (exit 1).\n\n## Global options\n\nAvailable on every command:\n\n| Flag | Purpose |\n|------|---------|\n| `--api-key <key>` | API key (overrides env/saved config) |\n| `-V, --version` | Print version |\n| `-h, --help` | Help for any command/subcommand |\n\n## auth\n\n```\npostnitro auth set-key <key>   # save to ~/.postnitro-cli/config.json\npostnitro auth status          # { configured, source, apiKey (masked) }\npostnitro auth clear           # remove saved key\n```\n\n> **Security:** `auth set-key` stores the API key in **plaintext** at `~/.postnitro-cli/config.json`. Restrict its file permissions (`chmod 600`), avoid shared or untrusted machines, and run `auth clear` to remove it. In CI, prefer `--api-key` or the `POSTNITRO_API_KEY` env var over the saved file.\n\n## defaults\n\n```\npostnitro defaults get\npostnitro defaults set [--template-id <id>] [--brand-id <id>] [--preset-id <id>] [--response-type PDF|PNG|DESIGN]\n```\nRequires at least one field. Resolution order per field: explicit flag → saved default → auto-select (when exactly one candidate exists).\n\n## template / brand / preset (discovery)\n\n```\npostnitro template list [--page <n>] [--limit <n>]\npostnitro preset list   [--page <n>] [--limit <n>]\npostnitro brand list    [--page <n>] [--limit <n>]\npostnitro brand get <id>\npostnitro brand create  (--name --handle --image [--company-detail] [--no-show-name|--no-show-handle|--no-show-image]) | --data <json> | --file <json>\npostnitro brand update <id> ...same as create...\n```\n`--data` (inline JSON object) overrides `--file`, which overrides the individual flags.\n\n## carousel\n\n```\npostnitro carousel import-template                 # prints the slide schema + rules\npostnitro carousel generate --context <text> [--type text|article|x] [--instructions <text>]\n                            [--template-id] [--brand-id] [--preset-id] [--response-type PDF|PNG|DESIGN]\n                            [--requestor-id <id>] [--wait]\npostnitro carousel import (--slides <json> | --file <path>)\n                          [--template-id] [--brand-id] [--response-type] [--requestor-id] [--wait]\npostnitro carousel status <embedPostId>            # progress + step logs\npostnitro carousel output <embedPostId>            # file URL(s) + designId + editorUrl\n```\n- `--type`: `text` (topic/text), `article` (article URL), `x` (X post URL).\n- `--response-type`: `PDF` (default) | `PNG` | `DESIGN`. `DESIGN` skips rendering — no file is produced, output has `designId` + `editorUrl` only.\n- `--wait`: poll to completion; returns final output incl. `designId` and `editorUrl`.\n- `--slides` (inline JSON) overrides `--file`; accepts a bare array or `{ \"slides\": [...] }`.\n- AI images: add `--generate-images` (+ optional `--image-placement`/`--image-strategy`/`--image-context`) — see [AI image generation](#ai-image-generation-generateimages).\n\n## image\n\nSingle-image posts. Mirrors `carousel`, but produces one image and `import` takes a **single slide object** (not an array).\n\n```\npostnitro image import-template                    # prints the image-slide schema + rules\npostnitro image generate --context <text> [--type text|article|x] [--instructions <text>]\n                         [--template-id] [--brand-id] [--preset-id] [--response-type PDF|PNG|DESIGN]\n                         [--requestor-id <id>] [--wait]\npostnitro image import (--slide <json> | --file <path>)\n                       [--template-id] [--brand-id] [--response-type] [--requestor-id] [--wait]\npostnitro image status <embedPostId>               # progress + step logs\npostnitro image output <embedPostId>               # file URL(s) + designId + editorUrl\n```\n- `--slide` (inline JSON) overrides `--file`; a **single object** (arrays are rejected — those are CAROUSEL-only). Accepts a bare object or `{ \"slides\": { ... } }`.\n- Allowed slide fields: `heading` (required), `sub_heading`, `description`, `cta_button`, `image`, `background_image`, plus `layoutType`/`layoutConfig` for the infographic layout. Any other field is rejected.\n- Infographic layout works on IMAGE too — set `layoutType: \"infographic\"` + `layoutConfig` (same schema as carousel; see below). Every column and content item needs a caller-provided `id`.\n- AI images: `--generate-images` (+ optional flags) works here too — see [AI image generation](#ai-image-generation-generateimages).\n\n## AI image generation (`generateImages`)\n\nOpt-in AI image generation, available on **every** generate/import command (carousel and image) and on `generate-and-schedule`. Images are generated and baked into the design before rendering, so they appear in the rendered file and in the editor.\n\n| Flag | Values | Default | Notes |\n|------|--------|---------|-------|\n| `--generate-images` | (boolean) | off | Opt in. Also implied by any flag below. |\n| `--image-context <text>` | string | — | **Required** when generating images: a short visual brief for the image prompts. |\n| `--image-placement <mode>` | `auto` \\| `background` \\| `in-line` | `auto` | `auto` = AI decides per slide. |\n| `--image-strategy <mode>` | `strategic` \\| `all` | `strategic` | `strategic` ≈ 50% of slides; `all` = every eligible slide. |\n\n- `--image-context` is required whenever image generation is enabled — the CLI fails fast if it's missing.\n- The two enums are validated client-side (fails fast on a bad value).\n- **Best-effort:** the post still completes if image generation fails or isn't permitted. With `--wait`, the result includes `imageGeneration` (the `GENERATE_IMAGES` job step); a `FAILED` status there (e.g. free plan, or over the org's AI-image quota) means the post completed without images. Without `--wait`, the step appears in `status` logs.\n- **Credits:** AI images consume the organization's **separate AI-image quota** — the post's slide-based `credits` are unchanged. Free plans cannot generate AI images.\n- Adds latency (real images are rendered); keep polling `status` until `COMPLETED`.\n\n## social\n\n```\npostnitro social list                 # { count, accounts: [{ id, platform, handle, name, accountType, status }] }\npostnitro social get <id>\npostnitro social disconnect <id> --yes # destructive\n```\n\n> **Destructive:** `social disconnect` removes the linked social account from your workspace. Scheduled posts targeting it will fail to publish, and restoring access requires reconnecting and re-authenticating. Requires `--yes`.\n\n## schedule\n\n```\npostnitro schedule list --from <date> --to <date>\npostnitro schedule create --status DRAFT|SCHEDULED --scheduled-at <iso>\n                          [--design-id <id>] [--file <json>]\n                          [--post-content <json>] [--selected-accounts <json>]\n                          [--instagram-post-settings <json>] [--tiktok-post-settings <json>]\n                          [--linkedin-post-settings <json>] [--threads-post-settings <json>]\n                          [--post-settings <json>]\npostnitro schedule get <id>\npostnitro schedule update <id> ...same flags as create...   # REPLACES state\npostnitro schedule delete <id> --yes\n```\n- **`schedule delete` is destructive:** it permanently cancels and removes the scheduled post — this cannot be undone. Requires `--yes`.\n- Requires either `--design-id` or non-empty `--post-content`.\n- `--scheduled-at` must be a **future** ISO-8601 datetime (trailing `Z`).\n- Inline JSON flags override the same field in `--file`.\n\n## generate-and-schedule\n\n```\npostnitro generate-and-schedule --context <text> --status DRAFT|SCHEDULED --scheduled-at <iso>\n                                [--post-type CAROUSEL|IMAGE] [ ...all generate flags... ]\n                                [--generate-images --image-context <text> ...]   # optional AI images\n                                [--design-id] [--file <json>]\n                                [--post-content] [--selected-accounts] [--*-post-settings] [--post-settings]\n```\nGenerates → waits → schedules in one call. `--post-type` defaults to `CAROUSEL` (use `IMAGE` for a single-image post). Also accepts the [AI image generation](#ai-image-generation-generateimages) flags. On scheduling failure the error includes the `designId` so you can retry `schedule create` without regenerating.\n\n## import-and-schedule\n\n```\npostnitro import-and-schedule --status DRAFT|SCHEDULED --scheduled-at <iso>\n                              [--post-type CAROUSEL|IMAGE]\n                              (--slides <json> | --slide <json> | --slides-file <path>)\n                              [--template-id] [--brand-id] [--response-type] [--requestor-id]\n                              [--generate-images --image-context <text> ...]   # optional AI images\n                              [--design-id] [--file <json>]\n                              [--post-content] [--selected-accounts] [--*-post-settings] [--post-settings]\n```\nImports your own content → waits → schedules in one call (the import-side counterpart of `generate-and-schedule`). `--post-type` defaults to `CAROUSEL` — pass `--slides` (array) for CAROUSEL or `--slide` (single object) for IMAGE; `--slides-file` reads either from a file.\n\n> **Flag note:** here `--file` is the **schedule body** (postContent/accounts/settings), matching `generate-and-schedule` — so slide content comes from `--slides` / `--slide` / `--slides-file`, not `--file`.\n\nAlso accepts the [AI image generation](#ai-image-generation-generateimages) flags. On scheduling failure the error includes the `designId` so you can retry `schedule create` without re-importing.\n\n---\n\n## Captions — `postContent`\n\nJSON object keyed by platform. At least one non-empty caption unless `--design-id` is set. Hashtags auto-extracted.\nKeys: `common`, `linkedin`, `instagram`, `tiktok`, `facebook`, `threads`.\n\n## Platform settings\n\n| Flag | Shape |\n|------|-------|\n| `--linkedin-post-settings` | `{\"postType\":\"carousel\\|document\\|image\\|reel\",\"postTitle\":\"...\"}` — `document` needs 5–90 char `postTitle` |\n| `--instagram-post-settings` | `{\"postType\":\"carousel\\|image\\|reel\",\"postAsStory\":false}` |\n| `--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}` |\n| `--threads-post-settings` | `{\"postType\":\"carousel\\|image\\|reel\"}` |\n| `--post-settings` (reel) | `{\"videoDuration\":30,\"audioId\":\"...\"}` |\n\n## Slide schema (import)\n\nFor **carousel** import: exactly one `starting_slide` (first), ≥1 `body_slide`, exactly one `ending_slide` (last). For **image** import it's a single object with no `type` field (see the `image` section above).\n\n| Field | Notes |\n|-------|-------|\n| `type` | `starting_slide` \\| `body_slide` \\| `ending_slide` (required) |\n| `heading` | required on every slide |\n| `sub_heading` | optional |\n| `description` | optional body text |\n| `image` | optional image URL (public); ignored if `layoutType: \"infographic\"` |\n| `background_image` | optional background URL |\n| `cta_button` | optional CTA text |\n| `layoutType` | `default` \\| `infographic` |\n| `layoutConfig` | required when `layoutType: \"infographic\"` |\n\nInfographic `layoutConfig` (works on both carousel and image slides):\n```json\n{\n  \"hasHeader\": true,\n  \"columnCount\": 1,\n  \"displayCounterAs\": \"counter\",  // \"counter\" (default) | \"none\"\n  \"columnDisplay\": \"grid\",        // \"grid\" (comparative, default) or \"cycle\" (sequential; data in FIRST column only)\n  \"columnData\": [\n    {\n      \"id\": \"col-1\",\n      \"header\": \"Column\",\n      \"content\": [\n        {\n          \"id\": \"item-1\",\n          \"icon\": null,\n          \"title\": \"Item\",\n          \"description\": \"<p dir=\\\"ltr\\\">HTML string</p>\",\n          \"titleEnabled\": true,\n          \"descriptionEnabled\": true\n        }\n      ]\n    }\n  ]\n}\n```\nMax 3 columns. Setting `layoutType: \"infographic\"` replaces the slide's `image`. **Every column and content item needs a caller-provided `id`** — the API does not auto-generate them. `description` is an HTML string. Omitted `layoutConfig` fields use the defaults above; if `layoutType` is `infographic` but `layoutConfig` is missing, the slide falls back to the default layout.\n\n## Environment variables\n\n| Variable | Default | Purpose |\n|----------|---------|---------|\n| `POSTNITRO_API_KEY` | – | API key |\n| `POSTNITRO_CONFIG_DIR` | `~/.postnitro-cli` | Config/defaults location |\n\nFile v1.2.0:examples/EXAMPLES.md\n\n# PostNitro CLI — Skill Examples\n\nReady-to-use files for the `postnitro` skill. Authenticate first\n(`postnitro auth set-key pn-...` or `export POSTNITRO_API_KEY=pn-...`).\n\n## Files\n\n| File | What it is | Use with |\n|------|------------|----------|\n| [import-default.json](import-default.json) | Basic 4-slide import (starting / body / body / ending) | `carousel import` |\n| [import-infographics.json](import-infographics.json) | Import with `grid` and `cycle` infographic body slides | `carousel import` |\n| [schedule-post.json](schedule-post.json) | A full `schedule` body (designId + accounts + caption + LinkedIn settings) | `schedule create --file` |\n\n## Import a carousel\n\n```bash\n# From a file\npostnitro carousel import --file examples/import-default.json --wait\n\n# With infographic slides\npostnitro carousel import --file examples/import-infographics.json --wait\n\n# Same JSON inline (overrides --file)\npostnitro carousel import --slides \"$(cat examples/import-default.json)\" --wait\n```\n\n## Generate with AI (no JSON file needed — flags only)\n\n```bash\npostnitro carousel generate --context \"5 LinkedIn growth tips\" --type text --wait\npostnitro carousel generate --context \"https://yourblog.com/post\" --type article --wait\npostnitro carousel generate --context \"https://x.com/user/status/123\" --type x --wait\n```\n\n## Schedule a finished design\n\nEdit `schedule-post.json` (set a real `designId` from the import/generate output and a real\n`socialAccountId` from `postnitro social list`), then:\n\n```bash\npostnitro schedule create --file examples/schedule-post.json\n```\n\nInline flags override any field in the file, e.g. change the time without editing the file:\n\n```bash\npostnitro schedule create --file examples/schedule-post.json --scheduled-at \"2027-01-15T09:00:00Z\"\n```\n\n## End-to-end (capture designId → schedule)\n\n```bash\nDID=$(postnitro carousel import --file examples/import-infographics.json --wait | jq -r .designId)\nLINKEDIN=$(postnitro social list | jq -r 'first(.accounts[] | select(.platform==\"linkedin\").id)')\npostnitro schedule create --status SCHEDULED --scheduled-at \"2026-12-31T13:00:00Z\" \\\n  --design-id \"$DID\" --selected-accounts \"[\\\"$LINKEDIN\\\"]\" \\\n  --linkedin-post-settings '{\"postType\":\"document\",\"postTitle\":\"Remote Work, Done Right\"}' \\\n  --post-content '{\"common\":\"New carousel 🚀 #remotework\"}'\n```\n\nSee [../references/cli-reference.md](../references/cli-reference.md) for the full command and schema reference.\n\nFile v1.2.0:skill-card.md\n\n## Description: <br>\nPostNitro helps an agent create professional social media carousel posts through the PostNitro Embed API, including AI-generated carousels and imported slide content. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[iammuneeb](https://clawhub.ai/user/iammuneeb) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nMarketing teams, creators, agencies, and automation developers use this skill to ask an agent to turn topics, text, articles, X posts, or structured slide content into ready-to-review carousel outputs. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill requires a PostNitro API key and brand/template identifiers, which could expose account access if shared carelessly. <br>\nMitigation: Keep credentials in environment variables, avoid echoing secrets in chat or logs, and rotate the API key if it may have been exposed. <br>\nRisk: Generated carousel content may be inaccurate, off-brand, or unsuitable for publication without human review. <br>\nMitigation: Review the returned PNG or PDF carousel before publishing and revise prompts, source material, or slide content when needed. <br>\nRisk: PostNitro API calls can consume account credits, with AI generation costing more than content import. <br>\nMitigation: Confirm the requested workflow, slide count, and expected credit cost before initiating generation. <br>\n\n\n## Reference(s): <br>\n- [ClawHub Skill Listing](https://clawhub.ai/iammuneeb/skills/postnitro-carousel) <br>\n- [PostNitro OpenClaw Skill Page](https://postnitro.ai/openclaw) <br>\n- [PostNitro Documentation](https://postnitro.ai/docs) <br>\n- [API Reference](references/api-reference.md) <br>\n- [Examples Index](examples/EXAMPLES.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Guidance, Shell commands, API Calls, Configuration instructions] <br>\n**Output Format:** [Markdown guidance with shell commands and JSON API request examples] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Guides the agent through asynchronous carousel initiation, status polling, output retrieval, and presentation of PNG or PDF download URLs.] <br>\n\n## Skill Version(s): <br>\n1.2.0 (source: target metadata) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v1.2.0:examples/import-default.json\n\n{\n  \"slides\": [\n    {\n      \"type\": \"starting_slide\",\n      \"heading\": \"5 LinkedIn Growth Tips\",\n      \"sub_heading\": \"For founders and creators\",\n      \"description\": \"Simple habits that compound into real reach.\",\n      \"cta_button\": \"Swipe →\"\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"Post when your audience is awake\",\n      \"description\": \"Check your analytics for peak hours and schedule around them, not around when you happen to be free.\"\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"Hook in the first line\",\n      \"description\": \"The first sentence decides whether anyone reads the rest. Lead with the payoff, not the setup.\"\n    },\n    {\n      \"type\": \"ending_slide\",\n      \"heading\": \"Pick one and start today\",\n      \"sub_heading\": \"Consistency beats intensity\",\n      \"description\": \"Follow for more practical growth playbooks.\",\n      \"cta_button\": \"Follow\"\n    }\n  ]\n}\n\nFile v1.2.0:examples/import-infographics.json\n\n{\n  \"slides\": [\n    {\n      \"type\": \"starting_slide\",\n      \"heading\": \"Remote Work, Done Right\",\n      \"sub_heading\": \"A 2-minute field guide\",\n      \"description\": \"The setup and habits that separate good remote workers from great ones.\",\n      \"cta_button\": \"Swipe →\"\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"The 4 pillars of a solid setup\",\n      \"description\": \"Get these right and everything else gets easier.\",\n      \"layoutType\": \"infographic\",\n      \"layoutConfig\": {\n        \"columnCount\": 2,\n        \"columnDisplay\": \"grid\",\n        \"displayCounterAs\": \"none\",\n        \"hasHeader\": true,\n        \"columnData\": [\n          {\n            \"header\": \"Space & Focus\",\n            \"content\": [\n              { \"title\": \"Dedicated Desk\", \"description\": \"A fixed spot signals to your brain that it's work time.\" },\n              { \"title\": \"Noise Control\", \"description\": \"Headphones or a closed door — pick one.\" }\n            ]\n          },\n          {\n            \"header\": \"Rhythm & Recovery\",\n            \"content\": [\n              { \"title\": \"Hard Stop Time\", \"description\": \"Set an end time and honor it.\" },\n              { \"title\": \"Lunch Away\", \"description\": \"Take 30 screen-free minutes.\" }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"type\": \"body_slide\",\n      \"heading\": \"A simple daily cadence\",\n      \"description\": \"Run your day in sequence, not in chaos.\",\n      \"layoutType\": \"infographic\",\n      \"layoutConfig\": {\n        \"columnCount\": 1,\n        \"columnDisplay\": \"cycle\",\n        \"displayCounterAs\": \"counter\",\n        \"hasHeader\": false,\n        \"columnData\": [\n          {\n            \"header\": \"Daily Flow\",\n            \"content\": [\n              { \"title\": \"Deep work first\", \"description\": \"90 minutes on the hardest task before any meetings.\" },\n              { \"title\": \"Batch comms\", \"description\": \"Two windows for Slack/email — not all day.\" },\n              { \"title\": \"Shutdown ritual\", \"description\": \"Write tomorrow's top 3, then close the laptop.\" }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"type\": \"ending_slide\",\n      \"heading\": \"Start with one change\",\n      \"sub_heading\": \"You don't need a perfect setup\",\n      \"description\": \"Follow for more remote-work playbooks.\",\n      \"cta_button\": \"Follow\"\n    }\n  ]\n}\n\nFile v1.2.0:examples/schedule-post.json\n\n{\n  \"status\": \"SCHEDULED\",\n  \"scheduledAt\": \"2026-12-31T13:00:00Z\",\n  \"designId\": \"<designId from carousel generate/import --wait>\",\n  \"selectedAccounts\": [\"<socialAccountId>\"],\n  \"postContent\": {\n    \"common\": \"New carousel is live 🚀 Save this one for later. #remotework #productivity\"\n  },\n  \"linkedinPostSettings\": {\n    \"postType\": \"document\",\n    \"postTitle\": \"Remote Work, Done Right\"\n  }\n}\n\nArchive v1.1.1: 8 files, 16405 bytes\n\nFiles: examples/EXAMPLES.md (2451b), examples/import-default.json (917b), examples/import-infographics.json (2322b), examples/schedule-post.json (400b), references/cli-reference.md (12644b), skill-card.md (2308b), SKILL.md (18605b), _meta.json (128b)\n\nFile v1.1.1:SKILL.md\n\n---\nname: postnitro\ndescription: Create on-brand social media carousels and single-image posts and schedule them to LinkedIn, Instagram, TikTok, and Threads from a single command. Turn a topic, article, or X thread into a finished multi-slide post or image — or import your own content — then publish or draft it automatically. Fully scriptable (JSON in, JSON out), so an AI agent can run the entire create-to-schedule workflow. Use this skill whenever the user wants to create a carousel, image post, slide post, or multi-slide content, repurpose an article, blog post, or X thread into slides, or automate and schedule social media posts. Use it to create and schedule content through PostNitro, not as a general social-media strategy advisor. Requires a PostNitro API key.\nhomepage: https://postnitro.ai\nmetadata: {\"openclaw\":{\"emoji\":\"🎠\",\"primaryEnv\":\"POSTNITRO_API_KEY\",\"requires\":{\"bins\":[],\"env\":[\"POSTNITRO_API_KEY\"]}}}\n---\n\n# PostNitro — Create & Schedule Social Posts\n\nPostNitro creates on-brand social media posts — multi-slide carousels and single images — and schedules them across LinkedIn, Instagram, TikTok, and Threads. This skill drives it from the command line, so an agent can take a topic, article, or your own content and produce a finished, scheduled post in one workflow. Every command is JSON in / JSON out — safe to script and chain.\n\n## Setup\n\n1. Install the CLI:\n   ```bash\n   npm install -g @postnitro/cli\n   ```\n2. Sign up at https://postnitro.ai and subscribe to a plan — the Embed API requires a **paid subscription** (no free tier). Then generate an API key at account settings → **Embed** → Generate API Key.\n3. Authenticate (in order of precedence: `--api-key` flag → env var → saved config):\n   ```bash\n   postnitro auth set-key pn-xxxx        # persists to ~/.postnitro-cli/config.json\n   export POSTNITRO_API_KEY=\"pn-xxxx\"    # or use an env var\n   ```\n4. Save defaults so you don't repeat template/brand/preset IDs on every call (the CLI's alternative to per-call flags — no env vars needed):\n   ```bash\n   postnitro defaults set --template-id <id> --brand-id <id> --preset-id <id> --response-type PDF\n   ```\n\n| Env var | Required | Purpose |\n|---------|----------|---------|\n| `POSTNITRO_API_KEY` | Yes* | API key (*unless passed via `--api-key` or saved with `auth set-key`) |\n\n> **Key rule:** `carousel generate`/`import` return an **`embedPostId`** (the async job). To *schedule* the result you need its **`designId`** (from the `--wait` output or `carousel output`). Never pass an `embedPostId` to `schedule`.\n\n> **Security:** `auth set-key` stores your API key in plaintext at `~/.postnitro-cli/config.json`. Restrict its file permissions and avoid shared or untrusted machines; run `auth clear` to remove it. This skill runs **no background processes, cron jobs, or startup scripts** — the only local state is the API key and saved defaults, both disclosed above.\n\n> **When NOT to use:** as a general social-media strategy advisor when no content is being produced. *(PostNitro composes with other tools — e.g., create a carousel here, then schedule it elsewhere — so pairing it with another scheduler is fine.)*\n\n## Core Workflow\n\nEvery create command is asynchronous — `--wait` handles the polling and returns the finished output (including `designId` and `editorUrl`) in one call.\n\n### 1. Create a post\n\nTwo independent choices decide which command you run:\n\n- **Post type** — a multi-slide `carousel` or a single `image`.\n- **Content source** — let AI write it (`generate`) or supply your own (`import`).\n\nThat's four commands:\n\n| | `generate` (AI writes it) | `import` (you supply content) |\n|---|---|---|\n| **`carousel`** (multi-slide) | `postnitro carousel generate` | `postnitro carousel import` |\n| **`image`** (single) | `postnitro image generate` | `postnitro image import` |\n\nAll four take `--template-id`/`--brand-id` (from flags or saved defaults) plus the modifiers in step 2, and every result includes the **`designId`** (needed to schedule) and an **`editorUrl`**.\n\n#### AI-generated (`generate`)\n\n```bash\npostnitro carousel generate \\\n  --context \"5 tips for growing your LinkedIn audience in 2026\" \\\n  --type text \\\n  --instructions \"Professional tone, actionable advice\" \\\n  --wait\n\n# Single image instead — same flags, just the image subcommand\npostnitro image generate --context \"Announce our new scheduling feature\" --wait\n```\n\n**`--type` values:**\n- `text` — `--context` is the topic/text to turn into a post\n- `article` — `--context` is an article URL to extract and convert\n- `x` — `--context` is an X (Twitter) post/thread URL\n\n`generate` also needs an AI preset (`--preset-id`, or a saved default).\n\n#### Import your own content (`import`)\n\n```bash\n# Carousel — slides is an ARRAY of typed slides (inline --slides overrides --file)\npostnitro carousel import --slides '{\"slides\":[\n  {\"type\":\"starting_slide\",\"heading\":\"Your Title\",\"description\":\"Intro text\"},\n  {\"type\":\"body_slide\",\"heading\":\"Key Point\",\"description\":\"Details here\"},\n  {\"type\":\"ending_slide\",\"heading\":\"Take Action!\",\"cta_button\":\"Learn More\"}\n]}' --wait\npostnitro carousel import --file ./slides.json --wait\n\n# Single image — slide is a SINGLE OBJECT (not an array), via --slide\npostnitro image import --slide '{\"heading\":\"Welcome!\",\"sub_heading\":\"Subtitle\",\"cta_button\":\"Learn more\"}' --wait\n```\n\n- **Carousel** (`--slides`, array): exactly 1 `starting_slide` (first), ≥1 `body_slide`, exactly 1 `ending_slide` (last); `heading` required on every slide. Run `postnitro carousel import-template` for the schema. Ready-to-use: [examples/import-default.json](examples/import-default.json), [examples/import-infographics.json](examples/import-infographics.json).\n- **Image** (`--slide`, one object): fields `heading` (required), `sub_heading`, `description`, `cta_button`, `image`, `background_image` (plus infographic — see step 2). Sending an array here is rejected. Run `postnitro image import-template` for the schema.\n\n### 2. Options for any create command\n\nThese layer onto any of the four commands above (and onto `generate-and-schedule`).\n\n#### Output format — `--response-type PDF | PNG | DESIGN`\n\nDefault `PDF` (single file URL). `PNG` returns one URL per slide. `DESIGN` **skips rendering** — no file is produced; you get just the `designId` + `editorUrl`, the fastest option when you only need to schedule or edit.\n\n#### AI image generation — `--generate-images` (any post type, any source)\n\nOpt in to have AI generate images and bake them into the design before rendering. Works on **all four** create commands (and `generate-and-schedule`), for both carousels and images. Requires an `--image-context` brief:\n\n```bash\npostnitro carousel generate --context \"How scheduling saves marketers time\" \\\n  --generate-images --image-context \"upbeat and professional, product-focused\" \\\n  --image-placement auto --image-strategy all --wait\n```\n\n- `--image-context <text>` — **required** when generating images: a short visual brief for the image prompts\n- `--image-placement auto|background|in-line` (default `auto` — AI decides per slide)\n- `--image-strategy strategic|all` (`strategic` ≈ 50% of slides, default; `all` = every eligible slide)\n\n**Best-effort:** the post still completes if images fail or aren't permitted. With `--wait`, the result carries an `imageGeneration` field (the `GENERATE_IMAGES` step); if its `status` is `FAILED`, its `message` explains why (e.g. free plan can't generate AI images, or the org is over its AI-image quota). AI images bill against the org's **separate AI-image quota**, not the post's slide credits, and add latency. Without `--wait`, the same step shows up in `status` logs.\n\n#### Infographic layout — `import` only\n\nOn either `import` command, set `layoutType: \"infographic\"` on a slide (with a `layoutConfig`) to render data columns (max 3) instead of an image. Every column and content item needs a caller-provided `id`, and each item `description` is an HTML string. See `carousel import-template` / `image import-template` for the full schema.\n\n### 3. Check status / get output (only if you didn't use `--wait`)\n\n```bash\npostnitro carousel status <embedPostId>   # progress + step logs; poll until COMPLETED\npostnitro carousel output <embedPostId>   # final file URL(s) + designId + editorUrl\n```\n(`image status` / `image output` work identically for image posts.)\n\nOutput is a PDF (single URL) or PNG (one URL per slide\n\nArchive v1.1.0: 8 files, 14525 bytes\n\nFiles: examples/EXAMPLES.md (2451b), examples/import-default.json (917b), examples/import-infographics.json (2322b), examples/schedule-post.json (400b), references/cli-reference.md (9421b), skill-card.md (2829b), SKILL.md (15394b), _meta.json (128b)\n\nArchive v1.0.1: 8 files, 13015 bytes\n\nFiles: examples/EXAMPLES.md (2451b), examples/import-default.json (917b), examples/import-infographics.json (2322b), examples/schedule-post.json (400b), references/cli-reference.md (7054b), skill-card.md (2526b), SKILL.md (13334b), _meta.json (128b)\n\nArchive v1.0.0: 8 files, 12451 bytes\n\nFiles: examples/EXAMPLES.md (2451b), examples/import-default.json (917b), examples/import-infographics.json (2322b), examples/schedule-post.json (400b), references/cli-reference.md (6384b), skill-card.md (2836b), SKILL.md (12468b), _meta.json (128b)","readmeExcerpt":"Skill: PostNitro Owner: iammuneeb Summary: Create on-brand social media carousels, single-image posts, and short videos, and schedule them to LinkedIn, Instagram, TikTok, and Threads from a single command. Turn a topic, article, or X thread into a finished multi-slide post, image, or video (with an optional audio track) — or import your own Tags: latest:1.3.0 Version history: v1.3.0 | 2026-08-18T22:11:09.440Z | user ","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"npm install -g @postnitro/cli"},{"language":"bash","snippet":"postnitro auth set-key pn-xxxx        # persists to ~/.postnitro-cli/config.json\n   export POSTNITRO_API_KEY=\"pn-xxxx\"    # or use an env var"},{"language":"bash","snippet":"postnitro defaults set --template-id <id> --brand-id <id> --preset-id <id> --response-type PDF"},{"language":"bash","snippet":"postnitro carousel generate \\\n  --context \"5 tips for growing your LinkedIn audience in 2026\" \\\n  --type text \\\n  --instructions \"Professional tone, actionable advice\" \\\n  --wait\n\n# Single image instead — same flags, just the image subcommand\npostnitro image generate --context \"Announce our new scheduling feature\" --wait\n\n# Video — same flags, plus the render length when you want the MP4 back\npostnitro video generate --context \"3 habits that make remote teams faster\" \\\n  --response-type MP4 --video-duration 30 --wait"},{"language":"bash","snippet":"# Carousel — slides is an ARRAY of typed slides (inline --slides overrides --file)\npostnitro carousel import --slides '{\"slides\":[\n  {\"type\":\"starting_slide\",\"heading\":\"Your Title\",\"description\":\"Intro text\"},\n  {\"type\":\"body_slide\",\"heading\":\"Key Point\",\"description\":\"Details here\"},\n  {\"type\":\"ending_slide\",\"heading\":\"Take Action!\",\"cta_button\":\"Learn More\"}\n]}' --wait\npostnitro carousel import --file ./slides.json --wait\n\n# Single image — slide is a SINGLE OBJECT (not an array), via --slide\npostnitro image import --slide '{\"heading\":\"Welcome!\",\"sub_heading\":\"Subtitle\",\"cta_button\":\"Learn more\"}' --wait\n\n# Video — same slide ARRAY as a carousel; each slide is a scene\npostnitro video import --file ./scenes.json --response-type MP4 --video-duration 30 --wait"},{"language":"bash","snippet":"postnitro audio list                       # find an audio track's ID\npostnitro video generate --context \"...\" --response-type MP4 --video-duration 30 --audio-id <audioId> --wait"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: postnitro\ndescription: Create on-brand social media carousels, single-image posts, and short videos, and schedule them to LinkedIn, Instagram, TikTok, and Threads from a single command. Turn a topic, article, or X thread into a finished multi-slide post, image, or video (with an optional audio track) — or import your own content — then publish or draft it automatically. Fully scriptable (JSON in, JSON out), so an AI agent can run the entire create-to-schedule workflow. Use this skill whenever the user wants to create a carousel, image post, video, reel, slide post, or multi-slide content, repurpose an article, blog post, or X thread into slides or a video, or automate and schedule social media posts. Use it to create and schedule content through PostNitro, not as a general social-media strategy advisor. Requires a PostNitro API key.\nhomepage: https://postnitro.ai\nmetadata: {\"openclaw\":{\"emoji\":\"🎠\",\"primaryEnv\":\"POSTNITRO_API_KEY\",\"requires\":{\"bins\":[],\"env\":[\"POSTNITRO_API_KEY\"]}}}\n---\n\n# PostNitro — Create & Schedule Social Posts\n\nPostNitro creates on-brand social media posts — multi-slide carousels, single images, and short videos — and schedules them across LinkedIn, Instagram, TikTok, and Threads. This skill drives it from the command line, so an agent can take a topic, article, or your own content and produce a finished, scheduled post in one workflow. Every command is JSON in / JSON out — safe to script and chain.\n\n## Setup\n\n1. Install the CLI:\n   ```bash\n   npm install -g @postnitro/cli\n   ```\n2. Sign up at https://postnitro.ai and subscribe to a plan — the Embed API requires a **paid subscription** (no free tier). Then generate an API key at account settings → **Embed** → Generate API Key.\n3. Authenticate (in order of precedence: `--api-key` flag → env var → saved config):\n   ```bash\n   postnitro auth set-key pn-xxxx        # persists to ~/.postnitro-cli/config.json\n   export POSTNITRO_API_KEY=\"pn-xxxx\"    # or use an env var\n   ```\n4. Save defaults so you don't repeat template/brand/preset IDs on every call (the CLI's alternative to per-call flags — no env vars needed):\n   ```bash\n   postnitro defaults set --template-id <id> --brand-id <id> --preset-id <id> --response-type PDF\n   ```\n\n| Env var | Required | Purpose |\n|---------|----------|---------|\n| `POSTNITRO_API_KEY` | Yes* | API key (*unless passed via `--api-key` or saved with `auth set-key`) |\n\n> **Key rule:** `carousel generate`/`import` return an **`embedPostId`** (the async job). To *schedule* the result you need its **`designId`** (from the `--wait` output or `carousel output`). Never pass an `embedPostId` to `schedule`.\n\n> **Security:** `auth set-key` stores your API key in plaintext at `~/.postnitro-cli/config.json`. Restrict its file permissions and avoid shared or untrusted machines; run `auth clear` to remove it. This skill runs **no background processes, cron jobs, or startup scripts** — the only local state is the API key and saved defaults, both disclosed ab"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn75qwv6mp7qy963qgzggb2qrn815sm8\",\n  \"slug\": \"postnitro\",\n  \"version\": \"1.3.0\",\n  \"publishedAt\": 1787091069440\n}"},{"path":"references/cli-reference.md","content":"# PostNitro CLI — Command Reference\n\nComplete reference for `@postnitro/cli`. Every command prints JSON on stdout (exit 0) or a\n`{ \"success\": false, \"error\": { \"message\": ... } }` object on stderr (exit 1).\n\n## Global options\n\nAvailable on every command:\n\n| Flag | Purpose |\n|------|---------|\n| `--api-key <key>` | API key (overrides env/saved config) |\n| `-V, --version` | Print version |\n| `-h, --help` | Help for any command/subcommand |\n\n## auth\n\n```\npostnitro auth set-key <key>   # save to ~/.postnitro-cli/config.json\npostnitro auth status          # { configured, source, apiKey (masked) }\npostnitro auth clear           # remove saved key\n```\n\n> **Security:** `auth set-key` stores the API key in **plaintext** at `~/.postnitro-cli/config.json`. Restrict its file permissions (`chmod 600`), avoid shared or untrusted machines, and run `auth clear` to remove it. In CI, prefer `--api-key` or the `POSTNITRO_API_KEY` env var over the saved file.\n\n## defaults\n\n```\npostnitro defaults get\npostnitro defaults set [--template-id <id>] [--brand-id <id>] [--preset-id <id>] [--response-type PDF|PNG|DESIGN]\n```\nRequires at least one field. Resolution order per field: explicit flag → saved default → auto-select (when exactly one candidate exists).\n\n## template / brand / preset (discovery)\n\n```\npostnitro template list [--page <n>] [--limit <n>]\npostnitro preset list   [--page <n>] [--limit <n>]\npostnitro brand list    [--page <n>] [--limit <n>]\npostnitro brand get <id>\npostnitro brand create  (--name --handle --image [--company-detail] [--no-show-name|--no-show-handle|--no-show-image]) | --data <json> | --file <json>\npostnitro brand update <id> ...same as create...\n```\n`--data` (inline JSON object) overrides `--file`, which overrides the individual flags.\n\n## carousel\n\n```\npostnitro carousel import-template                 # prints the slide schema + rules\npostnitro carousel generate --context <text> [--type text|article|x] [--instructions <text>]\n                            [--template-id] [--brand-id] [--preset-id] [--response-type PDF|PNG|DESIGN]\n                            [--requestor-id <id>] [--wait]\npostnitro carousel import (--slides <json> | --file <path>)\n                          [--template-id] [--brand-id] [--response-type] [--requestor-id] [--wait]\npostnitro carousel status <embedPostId>            # progress + step logs\npostnitro carousel output <embedPostId>            # file URL(s) + designId + editorUrl\n```\n- `--type`: `text` (topic/text), `article` (article URL), `x` (X post URL).\n- `--response-type`: `PDF` (default) | `PNG` | `DESIGN`. `DESIGN` skips rendering — no file is produced, output has `designId` + `editorUrl` only.\n- `--wait`: poll to completion; returns final output incl. `designId` and `editorUrl`.\n- `--slides` (inline JSON) overrides `--file`; accepts a bare array or `{ \"slides\": [...] }`.\n- AI images: add `--generate-images` (+ optional `--image-placement`/`--image-strategy`/`--image-context`) — see [AI image generation](#ai-image"},{"path":"examples/EXAMPLES.md","content":"# PostNitro CLI — Skill Examples\n\nReady-to-use files for the `postnitro` skill. Authenticate first\n(`postnitro auth set-key pn-...` or `export POSTNITRO_API_KEY=pn-...`).\n\n## Files\n\n| File | What it is | Use with |\n|------|------------|----------|\n| [import-default.json](import-default.json) | Basic 4-slide import (starting / body / body / ending) | `carousel import` |\n| [import-infographics.json](import-infographics.json) | Import with `grid` and `cycle` infographic body slides | `carousel import` |\n| [import-video.json](import-video.json) | 4-scene video import — background image, inline image, and an infographic scene (same slide array as a carousel) | `video import` |\n| [schedule-post.json](schedule-post.json) | A full `schedule` body (designId + accounts + caption + LinkedIn settings) | `schedule create --file` |\n\n## Import a carousel\n\n```bash\n# From a file\npostnitro carousel import --file examples/import-default.json --wait\n\n# With infographic slides\npostnitro carousel import --file examples/import-infographics.json --wait\n\n# Same JSON inline (overrides --file)\npostnitro carousel import --slides \"$(cat examples/import-default.json)\" --wait\n```\n\n## Import a video\n\nScenes use the same slide array as a carousel — one slide per scene. `--video-duration` is\nrequired when you want the rendered MP4 back.\n\n```bash\n# Rendered MP4, silent\npostnitro video import --file examples/import-video.json \\\n  --response-type MP4 --video-duration 30 --wait\n\n# With an audio track (IDs come from `postnitro audio list`, never a URL)\nAUDIO=$(postnitro audio list | jq -r '.audios[0].id')\npostnitro video import --file examples/import-video.json \\\n  --response-type MP4 --video-duration 30 --audio-id \"$AUDIO\" --wait\n\n# Design only — no render; set the duration later in the video maker\npostnitro video import --file examples/import-video.json --wait\n```\n\nA scene holds anything a carousel slide does — `image`, `background_image`, and\n`layoutType: \"infographic\"` all work, which is why this example uses one of each.\n\n**Want actual motion?** Point an `image` or `background_image` at a **`.gif`** (or use a\ntemplate whose elements carry animations). The API renders those through its enhanced\nvideo pipeline, which captures the movement; without a GIF or animations you get a\nstatic scene-by-scene video. Expect the enhanced render to take longer than the\n15-45s a plain one does.\n\n## Generate with AI (no JSON file needed — flags only)\n\n```bash\npostnitro carousel generate --context \"5 LinkedIn growth tips\" --type text --wait\npostnitro carousel generate --context \"https://yourblog.com/post\" --type article --wait\npostnitro carousel generate --context \"https://x.com/user/status/123\" --type x --wait\n\n# A video instead — each AI-written slide becomes a scene\npostnitro video generate --context \"3 habits that make remote teams faster\" \\\n  --response-type MP4 --video-duration 30 --wait\n```\n\n## Schedule a finished design\n\nEdit `schedule-post.json` (set a real `designId` from the import/gener"},{"path":"skill-card.md","content":"## Description:\n\nPostNitro helps an agent create, import, render, and schedule on-brand carousels, single-image social posts, and short videos across LinkedIn, Instagram, TikTok, and Threads using the PostNitro CLI.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[iammuneeb](https://clawhub.ai/user/iammuneeb)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users, marketers, developers, and agents use this skill to turn topics, articles, X threads, or structured slide JSON into draft or scheduled PostNitro social posts and videos.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill depends on the external @postnitro/cli package and a PostNitro API key with access to connected social accounts.\n\nMitigation: Install only when the package and account access are trusted, and prefer a scoped, temporary, or environment-provided API key.\n\nRisk: Saved authentication can store the PostNitro API key in plaintext on the local machine.\n\nMitigation: Prefer the POSTNITRO_API_KEY environment variable or --api-key flag on shared machines, restrict saved config file permissions, and clear saved auth when it is no longer needed.\n\nRisk: SCHEDULED actions can publish live social content to selected accounts at the configured time.\n\nMitigation: Confirm the target accounts, post content, and scheduled time before scheduling, and use DRAFT when the user is unsure.\n\n## Reference(s):\n\n- [PostNitro Skill Page](https://clawhub.ai/iammuneeb/skills/postnitro)\n- [PostNitro Homepage](https://postnitro.ai)\n- [CLI Reference](references/cli-reference.md)\n- [Skill Examples](examples/EXAMPLES.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with bash commands and JSON payloads]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Outputs may include PostNitro CLI commands that create, render, draft, or schedule social media content through a connected PostNitro account.]\n\n## Skill Version(s):\n\n1.3.0 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2318,"uniquenessScore":34,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T23:35:32.750Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T23:35:32.750Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-12T12:40:28.425Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}