🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Ghost Publisher

by @machinesofdesire

Publish markdown articles to any Ghost 5 CMS site. The first reference implementation of Publisher Interface v1 -- a CMS-agnostic contract for editorial work...

πŸ’‘ Examples

As a Python module (recommended for agents)

from publisher import GhostPublisher

pub = GhostPublisher() # reads env vars

post_id = pub.createPost({ "title": "A quiet argument about obsolescence", "excerpt": "Things that still run but no longer serve a purpose.", "body_md": open("article.md").read(), "tags": ["culture", "criticism"], "author": "staff_1", })

hosted = pub.uploadImage("https://cdn.example.com/hero.jpg", alt="Booth interior") pub.updatePost(post_id, {"featured_image_url": hosted, "image_alt_text": "Booth interior"})

url = pub.publishPost(post_id, {"send_newsletter": True}) print(f"Live at: {url}")

All seven Publisher Interface v1 methods are available on the GhostPublisher instance: createPost, updatePost, publishPost, schedulePost, deletePost, uploadImage, getPost.

As a CLI

Full pipeline (most common)

python3 publisher.py create-publish article.md \
  --title "Your Article Title" \
  --excerpt "A 1-2 sentence summary for SEO and previews" \
  --tags "ai,economics,analysis" \
  --image-url "https://cdn.example.com/header.jpg" \
  --image-alt "Description of the image" \
  --upload-image \
  --newsletter

Remove --newsletter to publish without emailing subscribers. Remove --upload-image if the image URL is already on a CDN you trust and you don't need Ghost's media store to host it.

Step-by-step

# 1. Create a draft (returns post_id)
python3 publisher.py create-draft --title "Title" --excerpt "Summary" --tags "tag1,tag2"

2. Inject markdown body

python3 publisher.py update-content article.md

3. Upload and attach a feature image

python3 publisher.py set-image https://cdn.example.com/hero.jpg --alt "Hero image" --upload

4. Schedule it, or publish it now

python3 publisher.py schedule 2026-05-01T09:00:00Z python3 publisher.py publish --newsletter

Other interface methods

python3 publisher.py get python3 publisher.py delete python3 publisher.py upload-image ./local.jpg --alt "alt text"


βš™οΈ Configuration

Required environment variables

  • GHOST_URL -- your Ghost site URL, e.g. https://yoursite.com or
  • https://yourpub.ghost.io
  • GHOST_ADMIN_API_KEY -- Admin API key from a Ghost custom integration.
  • Format: :

    To get your Admin API key

    1. Go to Ghost Admin -> Settings -> Integrations 2. Click "Add custom integration" 3. Name it (e.g. "OpenClaw Publisher") 4. Copy the Admin API Key -- it is a 24-char key_id, a colon, and a 64-char hex secret (format: XXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)

    Optional config file (GHOST_PUBLISHER_CONFIG)

    For non-secret settings (default author, agent-to-staff mapping, newsletter ID, max image size), point GHOST_PUBLISHER_CONFIG at a JSON file:

    {
      "default_author_id": "ghost_staff_id",
      "agent_author_map": {
        "staff_1": "ghost_staff_id_1",
        "staff_2": "ghost_staff_id_2"
      },
      "newsletter_id": "ghost_newsletter_id",
      "max_image_size_mb": 2
    }
    

    The agent_author_map lets a caller pass {"author": "staff_1"} and have the adapter resolve it to the right Ghost staff member without the caller needing to know internal Ghost IDs. Omit the map and everything falls back to default_author_id, or to the integration's default if that is also unset.

    Keep this file out of version control if it contains IDs you do not want public. No secret keys go in this file -- secrets come from env vars.


    View on ClawHub
    TERMINAL
    clawhub install ghost-publisher

    πŸ§ͺ Use this skill with your agent

    Most visitors already have an agent. Pick your environment, install or copy the workflow, then run the smoke-test prompt above.

    πŸ” Can't find the right skill?

    Search 60,000+ AI agent skills β€” free, no login needed.

    Search Skills β†’