Skip to main content

mdsend — File-based social media publisher

mdsend

Write markdown posts, run mdsend, and it cross-posts to your social media platforms.

The main purpose is simple: set up a git repo with a simple directory structure and publish from it to various destinations. Your posts are in a single unified format that works across different social media platforms. You get a version-controlled archive that can be queried and managed by AI should the need arise.

Want to know what you've been focusing on, what your next posts should be, how to improve your writing, or which tags to use? Just ask your AI tool — it can read the repo and answer and provide you with a perspective.

This approach keeps you disconnected from the destination network so you don't get pulled into everyone else's feeds.

Supported platforms

Platform Max chars Max media API auth
LinkedIn 3,000 1 image OAuth 2.0 (Bearer)
Bluesky 300 4 images AT Protocol (App Password)
Mastodon 500 4 images OAuth (Access Token)

How it works

Each post is a directory named YYYY-MM-DD_HH-MM_slug/ containing:

  • post.md — the post text (markdown or plain text)
  • Optional media files (jpg, png, gif, mp4, mov)
posts/
├── 2026-05-03_15-30_my-thoughts/
│   ├── post.md
│   └── image.jpg
└── 2026-05-04_18-00_hello-world/
    └── post.md

Per-post platform targeting

By default every post goes to all platforms. To control this per post, add an optional front matter block at the top of post.md:

---
platforms: [bluesky]
---

This post will only appear on Bluesky.
---
platforms: []
---

This post is a draft — it will never be published.

Installation

pip install mdsend

Or from source:

git clone https://github.com/algodesigner/mdsend
cd mdsend
pip install -e .

Setup

Create a .env file with your API credentials:

cp .env.example .env

Fill in the credentials for the platforms you want to use. See .env.example for the full list of required fields.

Usage

# Preview what would be posted (default — no API calls made)
cd /path/to/your/posts
mdsend

# Actually post live
mdsend --publish

# Post to specific platforms
mdsend --platforms bluesky
mdsend --platforms bluesky --publish

Creating a new post

# Create a post directory and open the editor
mdsend --new "my-post-slug"

This creates a directory like 2026-05-04_21-30_my-post-slug/ with a post.md file containing a front matter template, then opens it in your $EDITOR (or vi by default).

Dry run

mdsend runs in dry-run mode by default — it prints what would be posted without calling any API. Use --publish to post live.

Multi-post threading (Bluesky & Mastodon)

Posts longer than the platform limit are automatically split into threaded replies. Each chunk is prefixed with 🧵 (n/N) so readers know it's part of a multi-part post. Media is attached to the first chunk only. Links are moved to the first chunk so the preview card appears at the top of the thread.

Idempotent publishing

Each platform gets its own sentinel file under posts/.published/. Re-running is safe — already-published platforms are skipped.

License

BSD 3-Clause. See LICENSE.

Happy microblogging! ☕

Metadata

Release files for mdsend 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mdsend 0.3.2
File Size Uploaded
mdsend-0.3.2.tar.gz 14.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mdsend 0.3.2
File Interpreter ABI Platform
mdsend-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 29.9 kB

Release files / mdsend-0.3.2.tar.gz

Download URL mdsend-0.3.2.tar.gz
Size 14.6 kB
Tags Source
SHA-256 checksum
How to use checksums
cfa49a140c4adedf9427bd53611f386a3d512735b7ad7fc0d0ea525d1bfa1c84
BLAKE2b-256 checksum
How to use checksums
dda5d6b67936d3b7e4be82a6ca01436f015836cc3677e3e5d64ae0d17f8abfdc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release files / mdsend-0.3.2-py3-none-any.whl

Download URL mdsend-0.3.2-py3-none-any.whl
Size 15.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5e9260fef7731790a9fe700a04dc1dc8660b24a3d2bcdc4604dd96beb4ddf4ad
BLAKE2b-256 checksum
How to use checksums
189a7bd8c8fe9bed3bac69d96e5aa34c4302ba3686c45a4d7ffde80b8c06a684
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release history Release notifications | RSS feed

This release

0.3.2 This release

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page