Publish to Ghost from a Markdown file in one command (free, open-source)

Hi all,

Publishing a post with several images by hand in the editor always cost me ~15 minutes of plumbing per piece — paste the body, upload each image one by one, fill in title/slug/excerpt/tags, build the cards. So I wrote a small CLI that does it in one command and open-sourced it (MIT), in case it’s useful to anyone here.

ghost-md-publisher — you write in Markdown with YAML front-matter, and it publishes to Ghost via the Admin API:

npm install -g @oksigenia/ghost-md-publisher
ghost-publish ./my-article/

What it handles:

  • Images — finds local images (body, HTML and feature_image), processes them with sharp (resize, format, EXIF) and uploads them, rewriting the paths.
  • Native Ghost cards — image captions, video embeds (YouTube/Vimeo/Odysee/Rumble) and the Product Card, all from simple Markdown.
  • Upsert by slug — if the slug already exists it updates the post instead of duplicating it.
  • Validation before sending — checks Ghost’s limits (excerpt 300, alt 191…) and the front-matter up front, so you don’t fail after uploading images.
  • Creates the post as a draft by default, so nothing goes live without you.

Free and MIT, published to npm with provenance (OIDC trusted publishing, no tokens).

I’d love feedback: what’s missing, what would make it fit your workflow better? Happy to add it to the roadmap. Thanks!

3 Likes

Very nice. The “first party” ghst CLI can also do that, though:

Frankly, not with images and native Ghost cards.

I see a few “new” CLI tools for Ghost pop up lately − would be cool to potentially consolidate instead of splitting focus.

Also a bit unsure if it’s smart to disclose that (or what relevancy it has?)

Thanks, appreciate it! :folded_hands:

You’re right there are a few ways to get content in. The gap I was scratching is the rest of the round-trip: it processes and uploads your local images (resize/format/EXIF) and rewrites the paths, turns captions, embeds and the Product Card into native Ghost cards, validates the front-matter against Ghost’s limits before sending, and upserts by slug (updates instead of duplicating). So it’s less “markdown → post” and more “a folder with images → a finished draft, repeatably.”

Totally with you on not fragmenting, though — I’d rather compare notes than add noise. If there’s overlap worth consolidating, I’m all ears.

On the provenance bit — fair question. The CLI needs your Ghost Admin API key, so “is this package really the code in the repo, unmodified?” matters. npm provenance is a signed attestation tying the published package to the exact commit + build, so anyone can verify it hasn’t been tampered with before handing it a key. Not essential reading, just a trust signal.

Thanks again for taking a look!

Appreciate the response, though I do kinda feel like I am talking to an AI :smiley:

Good luck with the CLI!

1 Like

:sweat_smile: just not a native speaker, so I overthink my English. thanks for taking a look!