SkillAgentSearch skills...

Crier

Cross-post your content to dev.to, Hashnode, Medium, Bluesky, Mastodon, and more

Install / Use

/learn @queelius/Crier
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Crier

Cross-post your content to dev.to, Ghost, WordPress, Hashnode, Medium, Bluesky, Mastodon, Threads, Telegram, Discord, and more.

Like a town crier announcing your content to the world.

Getting Started

Quick Setup

pip install crier
cd your-blog
crier init

The init command walks you through:

  • Creating the .crier/ registry directory
  • Detecting your content directories
  • Configuring platforms with API keys

How It Works

  1. Your markdown posts with YAML front matter are the source of truth
  2. .crier/registry.yaml tracks what's published where
  3. crier audit shows what's missing or changed
  4. crier publish or audit --publish publishes content
# See what needs publishing
crier audit

# Publish a file to a platform
crier publish post.md --to devto

# Publish to multiple platforms
crier publish post.md --to devto --to bluesky --to mastodon

# Bulk publish missing content (interactive)
crier audit --publish

With Claude Code

Crier is designed to work with Claude Code for AI-assisted publishing. Install the skill with crier skill install, then just ask Claude naturally:

  • "Cross-post my latest article to all platforms"
  • "What articles haven't been published to Bluesky?"
  • "Publish this post to Mastodon with a good announcement"

Claude automatically detects when to use the crier skill and follows the workflow: audit, select, publish (with rewrites for short-form platforms).

Installation

pip install crier

Supported Platforms

| Platform | API Key Format | Notes | |----------|---------------|-------| | dev.to | api_key | Full article support | | Hashnode | token or token:publication_id | Full article support | | Medium | integration_token | Publish only (no edit/list) | | Ghost | https://site.com:key_id:key_secret | Full article support | | WordPress | site.wordpress.com:token or https://site.com:user:app_pass | Full article support | | Buttondown | api_key | Newsletter publishing | | Bluesky | handle:app_password | Short posts with link cards | | Mastodon | instance:access_token | Toots with hashtags | | Threads | user_id:access_token | Short posts (no edit support) | | Telegram | bot_token:chat_id | Channel/group posts | | Discord | webhook_url | Server announcements | | LinkedIn | access_token | Requires API access | | Twitter/X | any (copy-paste mode) | Generates tweet for manual posting |

Platform Notes

Blog Platforms (dev.to, Hashnode, Medium, Ghost, WordPress):

  • Full markdown article publishing
  • Preserves front matter (title, description, tags, canonical_url)
  • Best for long-form content

Newsletter Platforms (Buttondown):

  • Publishes to email subscribers
  • Full markdown support
  • Great for content repurposing

Social Platforms (Bluesky, Mastodon, LinkedIn, Twitter, Threads):

  • Creates short posts with link to canonical URL
  • Uses title + description + hashtags from tags
  • Best for announcing new content

Announcement Channels (Telegram, Discord):

  • Posts to channels/servers
  • Good for community announcements
  • Discord uses webhook embeds

Manual Mode

For platforms with restrictive API access (Medium, LinkedIn, Twitter/X), you can use manual (copy-paste) mode:

# Explicit manual mode with --manual flag
crier publish post.md --to medium --manual
crier publish post.md --to linkedin --manual

# Skip auto-opening browser
crier publish post.md --to twitter --manual --no-browser

Auto-manual mode: If you configure a platform's API key to "manual", crier automatically uses manual mode:

# Configure platform for manual mode (no API key needed)
crier config set twitter.api_key manual
crier config set linkedin.api_key manual

# Now these automatically use manual mode without --manual flag
crier publish post.md --to twitter
crier publish post.md --to linkedin

Manual mode workflow:

  1. Formats content for the platform
  2. Copies it to your clipboard
  3. Opens the compose page in your browser
  4. Asks if you successfully posted
  5. Records to registry only if you confirm

This ensures the registry accurately reflects what's actually published.

Configuration

Crier uses two configuration files:

Global Config (~/.config/crier/config.yaml)

API keys and profiles (shared across all projects):

platforms:
  devto:
    api_key: your_key_here
  bluesky:
    api_key: "handle.bsky.social:app-password"
  mastodon:
    api_key: "mastodon.social:access-token"
  twitter:
    api_key: manual    # Copy-paste mode
  medium:
    api_key: import    # URL import mode

profiles:
  blogs:
    - devto
    - hashnode
    - medium
  social:
    - bluesky
    - mastodon
  everything:
    - blogs           # Profiles can reference other profiles
    - social

Local Config (.crier/config.yaml)

Project-specific settings:

content_paths:
  - content                    # Directories to scan for markdown files
site_base_url: https://yoursite.com
exclude_patterns:
  - _index.md                  # Files to skip (Hugo section pages)
file_extensions:
  - .md
  - .mdx                       # Optional: for MDX content
default_profile: everything    # Used when no --to or --profile specified
rewrite_author: claude-code    # Default author for AI-generated rewrites

| Option | Purpose | |--------|---------| | content_paths | Directories to scan for content | | site_base_url | For inferring canonical URLs | | exclude_patterns | Filename patterns to skip | | file_extensions | Extensions to scan (default: .md) | | default_profile | Default platforms when none specified | | rewrite_author | Default --rewrite-author value |

Environment Variables

Environment variables override config files:

export CRIER_DEVTO_API_KEY=your_key_here
export CRIER_BLUESKY_API_KEY="handle.bsky.social:app-password"

Markdown Format

Crier reads standard markdown with YAML or TOML front matter:

---
title: "My Amazing Post"
description: "A brief description"
tags: [python, programming]
canonical_url: https://myblog.com/my-post
published: true
---

Your content here...

TOML front matter is also supported (delimited by +++):

+++
title = "My Amazing Post"
description = "A brief description"
tags = ["python", "programming"]

[extra]
canonical_url = "https://myblog.com/my-post"
+++

Your content here...

Commands

# Publishing
crier init                              # Interactive setup wizard
crier publish FILE --to PLATFORM        # Publish to platform(s)
crier publish FILE --to PLATFORM --manual  # Manual copy-paste mode
crier publish FILE --to bluesky --thread   # Publish as thread
crier audit                             # See what's missing/changed
crier audit --publish                   # Bulk publish interactively
crier audit --publish --yes             # Bulk publish without prompting

# Content Management
crier search                            # List all content
crier search --tag python --since 1w    # Filter by tag and date
crier status [FILE]                     # Show publication status
crier list PLATFORM                     # List your articles
crier delete FILE --from PLATFORM       # Delete from platform
crier archive FILE                      # Archive (exclude from audit)
crier unarchive FILE                    # Unarchive

# Scheduling
crier schedule list                     # List scheduled posts
crier schedule show ID                  # Show scheduled post details
crier schedule cancel ID                # Cancel scheduled post
crier schedule run                      # Publish due posts

# Analytics
crier stats                             # Show stats for all content
crier stats FILE                        # Show stats for specific file
crier stats --top 10                    # Top 10 by engagement
crier stats --refresh                   # Refresh from platforms

# Configuration
crier config show                       # Show configuration
crier config set KEY VALUE              # Set configuration
crier config llm show                   # Show LLM configuration
crier config llm test                   # Test LLM connection
crier doctor                            # Verify API keys work
crier skill install                     # Install Claude Code skill

Automation

Batch Mode

Use --batch for fully automated, non-interactive publishing (CI/CD):

# Batch mode implies --yes --json, skips manual/import platforms
crier publish post.md --to devto --to bluesky --batch
crier audit --publish --batch --long-form

Batch mode behavior:

  • Implies --yes (no confirmation prompts)
  • Implies --json (structured output for parsing)
  • Implies --only-api (skips manual/import platforms that require user interaction)

JSON Output

Use --json for machine-readable output:

crier publish post.md --to devto --json
crier audit --json

JSON output structure:

{
  "command": "publish",
  "file": "post.md",
  "results": [{"platform": "devto", "success": true, "url": "..."}],
  "summary": {"succeeded": 1, "failed": 0, "skipped": 0}
}

Auto-Rewrite

Use --auto-rewrite to generate short-form content using an LLM:

crier publish post.md --to bluesky --auto-rewrite

Simplest setup: If you have OPENAI_API_KEY set, it just works (defaults to gpt-4o-mini).

Or configure in ~/.config/crier/config.yaml:

# Minimal - just the API key (defaults to OpenAI + gpt-4o-mini)
llm:
  api_key: sk-...

# Or full config for Ollama/other providers
llm:
  base_url: http://localhost:11434/v1  # Ollama
  model: llama3
  # api_key: not needed for local Ollama

Environment variables (override config):

  • OPENAI_API_KEY — API key (auto-defaults to OpenAI endpoint + gpt-4o-mini)
  • OPENAI_BASE_URL — Custom endpoint (e.g., http://localhost:11434/v1 for Ollama)

Bul

Related Skills

View on GitHub
GitHub Stars13
CategoryContent
Updated2d ago
Forks1

Languages

Python

Security Score

95/100

Audited on Apr 1, 2026

No findings