Inklate skill · Publish

posts-create

Create a post on Inklate in one call — a draft, a scheduled post, or a publish-now, decided entirely by whether you pass a schedule time — with the server's…

frontmatter · SKILL.md+
name: posts-create
description: >
  Create a post on Inklate in one call — a draft, a scheduled post, or a publish-now,
  decided entirely by whether you pass a schedule time — with the server's per-channel
  validation riding along in the same response instead of a separate check. Covers
  LinkedIn, X (Twitter), Instagram, and Facebook today, with Mastodon, Threads, Bluesky,
  TikTok, and YouTube in platform review. Use when the user says "draft this on Inklate",
  "create a post", "get this ready to publish", or "post this now". Requires the Inklate
  CLI (npm i -g inklate) or the Inklate MCP connection. Reads social-context.md when
  present so drafts and autofixes stay on-voice. A draft with errors still saves — arming
  it with a schedule or publish time is the only thing the server refuses, and that
  refusal never leaves a partial write behind.
license: MIT
metadata:
  version: 0.2.0
  topics:
    - drafting
    - checking
  examplePrompt: "Draft this announcement on Inklate for LinkedIn and X and tell me if it's ready"
  pairsWith:
    - social-post
    - social-thread
    - social-crosspost
  mcpTools:
    - posts_create
    - posts_update
    - files_upload
  cliCommands:
    - posts create
    - posts update
    - files upload

Create a draft on real channels in one call and hand back the server's own verdict — the safe half of the loop, ending exactly where a human (or the posts-publish skill) takes over.

Transports

  • CLI (preferred): inklate (npm i -g inklate) — structured YAML on stdout (--json for JSON), progress on stderr, and typed exit codes: 3 no credentials, 4 a deliberate refusal — arming a not-ready post, or a plan limit — with its machine-readable payload on stdout, 5 not found, 6 the resource changed underneath you, 7 rate limited but safe to re-run later. Pass --no-input when running unattended so a missing flag fails loudly instead of prompting, and --yes to carry an approval the user has already given in chat. This skill never passes --scheduled-at on posts create — that turns the call into an arming attempt, which is posts-publish's job.
  • MCP (fallback): the Inklate MCP tools when the CLI is not installed.

Steps below name the MCP operation with the CLI form in parentheses; the fields are the same on both.

Connection check

  1. Run inklate auth check (MCP: organizations_list) first.
  2. On exit 3 (no credentials): interactively run inklate auth login; headless, the key comes from INKLATE_API_KEY=inklate_… in the environment or inklate auth set --token inklate_…. If neither transport is available at all, tell the user to install with npm i -g inklate (or connect at https://inklate.com/skills/connect?ref=skills-posts-create) and STOP.
  3. If multiple organizations exist, ask which one (CLI: --org <slug>).

Craft boundary

This skill owns create → read the verdict → fix judgment calls. The WRITING belongs to the paired craft skills: when social-post, social-thread, or social-crosspost is installed, get the draft from them first and feed their output in. Without them, use the user's text as given and make only the edits the server's response demands.

Context

Read social-context.md (project root, then .agents/social-context.md) if present. ## Voice and ## Never constrain any fix that rewrites text; ## Platforms resolves vague targets ("post this" → the user's primary channel). Proceed without it if absent.

Workflow

  1. Establish content and targets. Markdown is the input sugar: a --- line splits thread items on channels that thread. Confirm target channels; provider names ("x", "linkedin") resolve server-side when the organization has one channel per platform.
  2. If the post needs media from local files, upload them first with files_upload (CLI: inklate files upload ./photo.jpg — prints reusable file_… ids; the CLI also accepts local paths directly on --media and uploads them in-line). Media already on the web passes as a public https URL.
  3. Create the draft in one call. inklate posts create --content … --channel … --media … (MCP: posts_create with {content, channels, media}; autofix defaults to true). Never pass --scheduled-at here. The response IS the verdict — no separate check to run: a top-level ready, and per channel a content.text (the actual copy that channel will receive), errors[] (code, field, a human message with the real numbers, and a machine fix where one exists), and warnings[]. A draft with errors still saves fine — exit 0, the errors ride along on stdout; only arming a schedule or publish time is refused. Add --idempotency-key <key> when a create might be retried — a rerun replays instead of leaving two drafts of the same post behind.
  4. Autofix already ran before you saw the response. Default on, it silently repairs what it can — trim_to_fold, rebalance_thread, set_title — and reports every repair in fixes_applied (channel + kind; no extra call needed). Read out every entry as "channel — kind (auto-applied)" so nothing rewrites the user's words without them knowing. Pass --no-autofix (autofix: false) when the user wants to see the raw violations before anything is touched.
  5. For every error still remaining (autofix had nothing to offer, or was off), the message already names the real numbers — no code-to-English translation needed. If errors[].fixes offers a repair you want to apply, call inklate posts update <id> --per-channel '{"<channel>": {"content": "…"}}' (MCP: posts_update) with the corrected copy for just that channel; the response re-validates and returns the same shape, so there is no separate re-check step. When a fix would change meaning or trips ## Never, treat it as a judgment call instead — 2–3 concrete options to the user, not a guess.
  6. Stop once the draft matches the user's intent — ready or not. ready gates arming, never saving. Publishing and scheduling are the posts-publish skill's job (or the user's, in the dashboard): offer the next command (inklate posts publish post_abc123 --wait) but never run it from this skill. A stand-alone dry run against a stored post or inline text with nothing written is a handoff to inklate posts validate — mention it, don't run it here.

Quality bar

  • ready is the only publishability signal to trust — never infer it from the absence of one particular error code.
  • Every entry in fixes_applied is named to the user by channel and kind; a silent autofix is a bug.
  • The receipt's post ID is the contract: any later skill or command can pick the draft up from it.
  • This skill never passes --scheduled-at / a scheduled_at value — arming is posts-publish's call, even when the draft is already green.
  • A draft with errors is not a failure to hide: report it plainly, exit 0, and move straight to the fixes.
  • Judgment-call fixes are applied through posts update, never invented ahead of what the response's fixes array actually offered.
  • This skill never publishes, schedules, or deletes — its output is a validated draft. Editing or cancelling an existing post is posts-update's job.

Receipt

End with:

Post ID Channel Ready Autofix applied Remaining error
post_abc123 LinkedIn yes
post_abc123 X yes rebalance_thread
post_abc123 Instagram no media required (no image attached)

Below the table: whether the draft as a whole is ready (or which channels are parked and why), the exact next command to ship it (inklate posts publish post_abc123 --wait or the posts-publish skill), and any media file ids attached.

Related skills