--- name: ghost description: "Manage Ghost CMS blog posts via Admin API. Supports creating, updating, deleting, and listing posts. NEW: Upload images and set feature images for posts. Use when the user needs to programmatically manage Ghost blog content. Requires a JSON configuration file with API credentials." --- # Ghost CMS Admin API Manage your Ghost blog posts programmatically through the Admin API. ## Features - 📝 **Create/Update/Delete posts** - Full CRUD operations - 🖼️ **Upload images** - Upload images to Ghost and get URL - 🎨 **Feature images** - Set cover images for posts - 📊 **List posts** - View recent posts with status - 🏷️ **Tags support** - Add tags to posts ## Prerequisites ### 1. Get Admin API Key 1. Log in to your Ghost Admin panel (`https://your-blog.com/ghost/`) 2. Go to **Settings** → **Integrations** 3. Click **"Add custom integration"** 4. Copy the **Admin API Key** (format: `id:secret`) ### 2. Create Configuration File **唯一调用方式:自定义配置文件路径(项目隔离)** Create a JSON config file for your site: Example: `/Users/ethan/.openclaw/workspace/projects/fuye/ghost-admin.config.json` ```json { "api_url": "https://fu-ye.com/ghost/api/admin", "admin_api_key": "your-id:your-secret" } ``` ## CLI Usage ### Method: Custom Config Path (唯一方式) ```bash python3 scripts/ghost.py list --config "../../projects/fuye/ghost-admin.config.json" python3 scripts/ghost.py create "Title" "Content" --config "../../projects/fuye/ghost-admin.config.json" python3 scripts/ghost.py upload image.png --config "../../projects/fuye/ghost-admin.config.json" ``` ## Python API Usage ### Method: Custom Config Path (唯一方式) ```python import sys import os sys.path.insert(0, os.path.expanduser("~/.openclaw/workspace/skills/ghost/scripts")) import ghost # 唯一方式:通过配置文件路径获取配置 config = ghost.get_config(config_path="../../projects/fuye/ghost-admin.config.json") # Create post result = ghost.create_post( config=config, title="My Article Title", content="

Title

Content...

", status="published", tags=["tech", "news"] ) ``` ### 3. Install Dependencies ```bash pip3 install requests pyjwt --user ``` ## Python API Usage ### Create a Post ```python import sys import os sys.path.insert(0, os.path.expanduser("~/.openclaw/workspace/skills/ghost/scripts")) import ghost # 通过配置文件路径获取配置(唯一方式) config = ghost.get_config(config_path="../../projects/fuye/ghost-admin.config.json") # Create post with HTML content result = ghost.create_post( config=config, title="My Article Title", content="

Title

Content...

", # HTML format status="published", # or "draft" tags=["tech", "news"] ) ``` ### Upload Image ```python # Upload image and get URL image_url = ghost.upload_image(config, "/path/to/image.jpg") print(f"Image URL: {image_url}") ``` ### Create Post with Feature Image ```python # Upload cover image first cover_image_url = ghost.upload_image(config, "cover.jpg") # Create post with feature image result = ghost.create_post( config=config, title="Article with Cover", content="

Article content...

", status="published", feature_image=cover_image_url, # Set cover image tags=["featured"] ) ``` ### List Posts ```python posts = ghost.list_posts(config, limit=20) for post in posts: print(f"{post['title']} - {post['status']}") ``` ### Update Post ```python ghost.update_post( config=config, post_id="post-id-here", title="New Title", status="published" ) ``` ## CLI Usage ### Setup ```bash # Install dependencies pip3 install requests pyjwt --user ``` ### Create a Post **As draft (default):** ```bash python3 scripts/ghost.py create "My Article Title" "

Article content in HTML

" --config "../../projects/fuye/ghost-admin.config.json" ``` **Publish immediately:** ```bash python3 scripts/ghost.py create "Breaking News" "

Content here

" --status published --config "../../projects/fuye/ghost-admin.config.json" ``` **With tags:** ```bash python3 scripts/ghost.py create "Tech News" "

Content

" --status published --tags "tech,news,ai" --config "../../projects/fuye/ghost-admin.config.json" ``` ### Upload Image ```bash python3 scripts/ghost.py upload cover.png --config "../../projects/fuye/ghost-admin.config.json" ``` ### Update a Post ```bash # Update title python3 scripts/ghost.py update 5f8c3c2e8c3d2e1f3a4b5c6d --title "New Title" --config "../../projects/fuye/ghost-admin.config.json" # Update content python3 scripts/ghost.py update 5f8c3c2e8c3d2e1f3a4b5c6d --content "

New content

" --config "../../projects/fuye/ghost-admin.config.json" # Publish a draft python3 scripts/ghost.py update 5f8c3c2e8c3d2e1f3a4b5c6d --status published --config "../../projects/fuye/ghost-admin.config.json" ``` ### Delete a Post ```bash python3 scripts/ghost.py delete 5f8c3c2e8c3d2e1f3a4b5c6d --config "../../projects/fuye/ghost-admin.config.json" ``` ### List Posts ```bash # List 10 most recent posts (default) python3 scripts/ghost.py list --config "../../projects/fuye/ghost-admin.config.json" # List 20 posts python3 scripts/ghost.py list 20 --config "../../projects/fuye/ghost-admin.config.json" ``` ## Common Workflows ### Publish with Cover Image ```python import sys import os sys.path.insert(0, os.path.expanduser("~/.openclaw/workspace/skills/ghost/scripts")) import ghost # 唯一方式:通过配置文件路径获取配置 config = ghost.get_config(config_path="../../projects/fuye/ghost-admin.config.json") # Upload cover image image_url = ghost.upload_image(config, "/path/to/cover.jpg") # Create post with cover result = ghost.create_post( config=config, title="Featured Article", content="

Article content...

", status="published", feature_image=image_url, tags=["featured", "tech"] ) print(f"Published: {result['url']}") ``` ### Batch Operations ```bash # List all drafts python3 scripts/ghost.py list 100 --config "../../projects/fuye/ghost-admin.config.json" | grep "🟡" # Update specific post python3 scripts/ghost.py update --tags "featured" --config "../../projects/fuye/ghost-admin.config.json" ``` ## API Reference ### ghost.get_config(config_path) **唯一方式**获取配置。 **Parameters:** - `config_path` - Path to JSON configuration file (e.g., `"../../projects/fuye/ghost-admin.config.json"`) **Returns:** Config dict with api_url and admin_api_key ### ghost.create_post(config, title, content, status='draft', tags=None, feature_image=None) Create a new post. **Parameters:** - `config` - Configuration dict from `get_config(config_path)` - `title` - Post title - `content` - HTML content - `status` - 'draft' or 'published' - `tags` - List of tag names - `feature_image` - URL of cover image (optional) **Returns:** Post dict with id, url, status ### ghost.upload_image(config, image_path) Upload an image to Ghost. **Parameters:** - `config` - Configuration dict - `image_path` - Local path to image file **Returns:** Image URL string ### ghost.list_posts(config, limit=10) List recent posts. **Returns:** List of post dicts ### ghost.update_post(config, post_id, **kwargs) Update existing post. **Parameters:** - `post_id` - Post ID to update - `title` - New title (optional) - `content` - New content (optional) - `status` - New status (optional) - `tags` - New tags (optional) ### ghost.delete_post(config, post_id) Delete a post. ## Troubleshooting **Error: No module named 'jwt'** → Install: `pip3 install pyjwt --user` **Error: 401 Unauthorized** → Check your Admin API Key is correct and not expired **Error: 404 Not Found** → Verify api_url in config file ends with `/ghost/api/admin` **Error: Config file not found** → Ensure config_path is correct relative to your working directory **Image upload fails** → Check image file exists and is under 10MB → Supported formats: JPG, PNG, GIF ## References - API Documentation: [references/api.md](references/api.md) - Ghost Official Docs: https://ghost.org/docs/admin-api/