← Back to Skills Marketplace
liverock

Ghost-Writer Sync

by Peter Lum · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ⚠ suspicious
72
Downloads
1
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install ghost-writer-sync
Description
Pulls published blog posts from Substack and Ghost into an Obsidian or Logseq vault for AI-assisted repurposing.
README (SKILL.md)

Ghost-Writer Sync

Automatically pulls your published blog posts (Substack / Ghost) into your local Obsidian or Logseq vault for AI-assisted repurposing.

How It Works

Blog Source  →  Fetch Posts  →  HTML → Markdown  →  Write to Vault
(Substack RSS / Ghost API)       (stdlib)         (frontmatter + body)
  1. Fetch — Pulls published posts from each configured source
  2. Convert — Transforms HTML content to clean Markdown using a stdlib-only converter
  3. Write — Saves each post as a Markdown file with rich frontmatter in your vault

Supported Sources

Source Auth Notes
Substack None (public RSS) Reads the /feed endpoint
Ghost Content API key (id:secret) Uses Admin API JWT auth

Output Formats

Format Frontmatter Filename
Obsidian YAML block (--- delimited) {slug}.md
Logseq Property list (key:: value) {date} {slug}.md

Frontmatter Fields

Every synced post includes:

Field Description
title Post title
source substack or ghost
url Original post URL
published Publication date
synced Timestamp of last sync
post_id Stable hash-based ID for dedup
tags (Ghost only) Tag names
excerpt (Ghost only) Post excerpt
feature_image (Ghost only) Hero image URL

Usage

Add a source

# Substack — just the URL
python3 sync.py add-substack --url https://example.substack.com

# Ghost — URL + API key
python3 sync.py add-ghost --url https://myblog.ghost.io --api-key abc123:def456...

Run a sync

python3 sync.py sync --vault /path/to/obsidian-vault

Check config

python3 sync.py list
python3 sync.py config

Repurposing Workflow

Once posts are in your vault, use your AI assistant to:

  • Rewrite posts as Twitter/X threads
  • Generate LinkedIn summaries
  • Create newsletter compilations
  • Extract key quotes and talking points
  • Draft follow-up posts based on themes

Posts land as standard Markdown files, so they work with any Obsidian plugin, Logseq graph, or AI tool that reads .md files.

Usage Guidance
Before installing, be aware of two main issues: (1) The README/arguments claim you supply a 'Ghost Content API key', but the code builds an Admin JWT and calls the Ghost admin API — that requires an Admin-style secret (id:secret) and is more powerful than a read-only Content API key. Only provide an admin key if you trust the skill and understand the privileges you’re granting. (2) The skill will persist the provided Ghost key in a local JSON config file (unencrypted), so treat that file as sensitive: store it in a secure location, restrict filesystem permissions, or avoid storing keys at all by passing them at runtime. Additional precautions: review the full sync.py yourself (or run it in a sandbox) to confirm there are no unexpected network destinations or behaviors, back up your vault before first run, and prefer using Substack (public RSS) or a documented read-only Content API flow if you need lower privilege.
Capability Analysis
Type: OpenClaw Skill Name: ghost-writer-sync Version: 1.0.0 The skill bundle provides legitimate functionality for syncing blog posts but contains a critical shell injection vulnerability in SKILL.md. The tool execution commands (e.g., sync_posts, add_ghost) wrap user-provided arguments like 'config', 'vault', and 'api_key' in double quotes within a shell command template, allowing an attacker to execute arbitrary code via crafted inputs. Furthermore, the script requires Ghost Admin API credentials (id:secret format) while the documentation incorrectly labels them as Content API keys, potentially misleading users into providing higher-privilege access than intended.
Capability Assessment
Purpose & Capability
The skill's stated purpose (sync Substack/Ghost posts into a vault) aligns with its code which fetches RSS and CMS posts and writes Markdown. However, SKILL.md repeatedly refers to a 'Ghost Content API key' while the code (_ghost_jwt_token and the API endpoint) constructs an Admin JWT and uses the /ghost/api/admin/ endpoint. Content API keys and Admin API keys are different; requiring an Admin-style key is more privileged than the documentation implies.
Instruction Scope
The SKILL.md instructions are bounded to fetching Substack RSS and Ghost posts, converting HTML to Markdown, and writing files to a user-specified vault/config. That scope matches the code. The skill will persist configuration (including supplied Ghost API key) to a local JSON config file, which means secrets you supply are stored on disk. The code appears to contact only the declared sources (Substack RSS and Ghost admin API) and writes local files; there are no additional network destinations described in SKILL.md.
Install Mechanism
No install spec — instruction-only with an included Python script. Nothing is downloaded from external URLs or installed automatically, which minimizes install-time risk.
Credentials
No environment variables are requested. The only credential flow is a Ghost API key passed as a command argument (and then stored in config). This is reasonable for a CMS sync tool, but the earlier mismatch (Content API vs Admin API) matters: asking for an Admin-style key is more privileged than a read-only Content API key and should be explicitly declared so users understand the sensitivity. Storing the key unencrypted in config is another data exposure concern.
Persistence & Privilege
The skill does not request permanent platform-wide privileges (always:false). Its persistence is limited to writing a local JSON config and Markdown files to whichever vault path the user provides, which is expected for this functionality.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install ghost-writer-sync
  3. After installation, invoke the skill by name or use /ghost-writer-sync
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
# Ghost-Writer Sync <div align="center"> **Your blog posts, in your vault, ready for AI.** [![OpenClaw Skill](https://img.shields.io/badge/OpenClaw-Skill-blue)](https://openclaw.dev) [![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-3776AB)](https://python.org) [![License: MIT](https://img.shields.io/badge/License-MIT-green)](LICENSE) [![Zero Dependencies](https://img.shields.io/badge/Dependencies-Zero-brightgreen)]() </div> --- ## The Problem You publish on Substack or Ghost. You want to repurpose those posts — turn them into threads, newsletters, summaries, or follow-ups. But your posts live on a remote CMS, and your AI tools live in your local Obsidian or Logseq vault. The gap between them is manual copy-paste. ## The Solution **Ghost-Writer Sync** bridges that gap. One command pulls all your published blog posts into your local vault as Markdown files with rich metadata. Your AI assistant can then read, remix, and repurpose them directly. ```bash python3 sync.py sync --vault ~/my-obsidian-vault ``` --- ## Features - **Substack support** — reads the public RSS feed, no API key needed - **Ghost support** — connects via Content API with admin JWT auth - **HTML to Markdown** — converts rich post content to clean Markdown - **Dual format** — Obsidian (YAML frontmatter) or Logseq (property list) - **Rich metadata** — title, URL, publish date, tags, excerpts, sync timestamp - **Zero dependencies** — pure Python standard library --- ## Quick Start ```bash # Add a Substack publication python3 ghost-writer-sync/sync.py add-substack --url https://example.substack.com # Add a Ghost blog python3 ghost-writer-sync/sync.py add-ghost --url https://myblog.ghost.io --api-key abc123:def456... # Sync everything to your vault python3 ghost-writer-sync/sync.py sync --vault ~/ObsidianVault ``` Posts appear in `~/ObsidianVault/Ghost-Writer/` as `.md` files. --- ## Supported Sources | Source | Authentication | What it fetches | |--------|---------------|-----------------| | Substack | None (public RSS) | Title, URL, date, full HTML body | | Ghost | Content API key (`id:secret`) | Title, URL, date, HTML body, tags, excerpt, feature image | --- ## Output Formats ### Obsidian ```markdown --- title: "My Blog Post" source: substack url: https://example.substack.com/p/my-post published: 2024-03-15 synced: 2024-03-20T12:00:00Z post_id: a1b2c3d4e5f6 --- # Post content in Markdown... ``` ### Logseq ```markdown title:: My Blog Post source:: substack url:: https://example.substack.com/p/my-post published:: 2024-03-15 synced:: 2024-03-20T12:00:00Z Post content in Markdown... ``` --- ## Repurposing Ideas Once posts are synced into your vault: - Rewrite as **Twitter/X threads** - Generate **LinkedIn summaries** - Compile into a **weekly newsletter** - Extract **key quotes and talking points** - Draft **follow-up posts** based on themes - Build a **content calendar** from your archive --- ## Project Structure ``` ghost-writer-sync/ ├── SKILL.md # OpenClaw skill definition └── sync.py # Core sync engine (single file, stdlib only) ``` --- ## Requirements - Python 3.10 or later - No external packages --- ## License MIT
Metadata
Slug ghost-writer-sync
Version 1.0.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is Ghost-Writer Sync?

Pulls published blog posts from Substack and Ghost into an Obsidian or Logseq vault for AI-assisted repurposing. It is an AI Agent Skill for Claude Code / OpenClaw, with 72 downloads so far.

How do I install Ghost-Writer Sync?

Run "/install ghost-writer-sync" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Ghost-Writer Sync free?

Yes, Ghost-Writer Sync is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Ghost-Writer Sync support?

Ghost-Writer Sync is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Ghost-Writer Sync?

It is built and maintained by Peter Lum (@liverock); the current version is v1.0.0.

💬 Comments