Crier - Cross-Post Your Content Everywhere
CLI tool for cross-posting content to multiple platforms including dev.to, Bluesky, Mastodon, Hashnode, Medium, and more. Supports markdown with frontmatter, automatic platform-specific formatting, and GitHub Actions integration.
Resources & Distribution
Source Code
Package Registries
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.
Installation
pip install crier
Quick Start
# Configure your API keys
crier config set devto.api_key YOUR_API_KEY
crier config set bluesky.api_key "handle.bsky.social:app-password"
crier config set mastodon.api_key "mastodon.social:access-token"
# Publish a markdown file
crier publish post.md --to devto
# Publish to multiple platforms at once
crier publish post.md --to devto --to bluesky --to mastodon
# List your articles
crier list devto
# Update an existing article
crier update devto 12345 --file updated-post.md
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 |
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
Configuration
API keys can be set via:
Config file (
~/.config/crier/config.yaml):platforms: devto: api_key: your_key_here bluesky: api_key: "handle.bsky.social:app-password" mastodon: api_key: "mastodon.social:access-token"Environment variables:
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 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...
Commands
crier publish FILE [--to PLATFORM]... # Publish to platform(s)
crier update PLATFORM ID --file FILE # Update existing article
crier list PLATFORM # List your articles
crier config set KEY VALUE # Set configuration
crier config show # Show configuration
crier platforms # List available platforms
Getting API Keys
dev.to
- Go to https://dev.to/settings/extensions
- Generate API key
Hashnode
- Go to https://hashnode.com/settings/developer
- Generate Personal Access Token
Medium
- Go to https://medium.com/me/settings/security
- Generate Integration Token
Bluesky
- Go to Settings → App Passwords
- Create an app password
- Use format:
yourhandle.bsky.social:xxxx-xxxx-xxxx-xxxx
Mastodon
- Go to Settings → Development → New Application
- Create app with
write:statusesscope - Use format:
instance.social:your-access-token
Twitter/X
Uses copy-paste mode - generates formatted tweet text for manual posting. No API setup required. Just set any placeholder value:
crier config set twitter.api_key manual
Ghost
- Go to Settings → Integrations → Add custom integration
- Copy the Admin API Key (format:
key_id:key_secret) - Use format:
https://yourblog.com:key_id:key_secret
WordPress
WordPress.com:
- Go to https://developer.wordpress.com/apps/
- Create an app and get OAuth token
- Use format:
yoursite.wordpress.com:access_token
Self-hosted WordPress:
- Go to Users → Profile → Application Passwords
- Create a new application password
- Use format:
https://yoursite.com:username:app_password
Buttondown
- Go to https://buttondown.email/settings/programming
- Copy your API key
- Use format:
api_key
Threads
- Create a Meta Developer account at https://developers.facebook.com/
- Create an app with Threads API access
- Get your user_id and access_token
- Use format:
user_id:access_token
Telegram
- Message @BotFather to create a bot and get the bot token
- Add your bot as admin to your channel
- Get your channel’s chat_id (e.g.,
@yourchannelor numeric ID) - Use format:
bot_token:chat_id
Discord
- Go to Server Settings → Integrations → Webhooks
- Create a new webhook for your announcement channel
- Copy the webhook URL
- Use the full URL as the API key
License
MIT
Related Resources
Explore related blog posts, projects, and publications