XPost#
XPost is a social media cross-posting tool that differs from others by using streaming APIs to allow instant, zero-input cross-posting. this means you can continue posting on your preferred platform without using special apps.
XPost tries to support as many features as possible. for example, when cross-posting from mastodon to bluesky, unsupported file types will be attached as links. posts with mixed media or too many files will be split and spread across text.
the tool may undergo breaking changes as new features are added, so proceed with caution when deploying.
Installation#
Native#
first install ffmpeg, ffprobe and libmagic, make sure that ffmpeg is available on PATH! ffmpeg and libmagic are required to crosspost media.
then get uv and sync the project
uv sync
generate settings.json on first launch
uv run main.py
Docker Compose#
the official immage is available on docker hub. example compose.yaml. this assumes that data dir is ./data, and env file is ./.config/docker.env. add :Z to volume mounts for podman.
services:
xpost:
image: melontini/xpost:latest
restart: unless-stopped
env_file: ./.config/docker.env
volumes:
- ./data:/app/data
Settings#
the tool allows you to specify an input and multiple outputs to post to.
some options accept a envvar syntax:
{
"token": "env:TOKEN"
}
Inputs#
all inputs have common options.
{
"options": {
"regex_filters": [ //posts matching any of the following regexes will be skipped
"(?i)\\b(?:test|hello|hi)\\b"
]
}
}
Bluesky Jetstream#
listens to repo operation events emmited by Jetstream. handle becomes optional if you specify a DID.
{
"type": "bluesky-jetstream-wss",
"handle": "env:BLUESKY_HANDLE", // handle (e.g. melontini.me)
"did": "env:BLUESKY_DID", // use a DID instead of handle (avoids handle resolution)
"jetstream": "wss://jetstream2.us-east.bsky.network/subscribe" //optional, change jetstream endpoint
}
Mastodon WebSocket mastodon-wss#
listens to the user's home timeline for new posts, crossposts only the public/unlisted ones by the user.
{
"type": "mastodon-wss", // type
"instance": "env:MASTODON_INSTANCE", // mastodon api compatible instance
"token": "env:MASTODON_TOKEN", // Must be a mastodon token. get from something like phanpy + webtools. or https://getauth.thms.uk/?client_name=xpost&scopes=read:statuses%20write:statuses%20profile but doesn't work with all software
"options": {
"allowed_visibility": [
"public",
"unlisted"
]
}
}
any instance implementing /api/v1/instance, /api/v1/accounts/verify_credentials and /api/v1/streaming?stream will work fine.
confirmed supported:
- Mastodon
- Iceshrimp.NET
- Akkoma
confirmed unsupported:
- Mitra
- Sharkey
Misskey WebSocket#
listens to the homeTimeline channel for new posts, crossposts only the public/home ones by the user.
IMPORTANT: Misskey WSS does Not support deletes, you must delete posts manually. if you know how i can listen to all note events, i would appreciate your help.
{
"type": "misskey-wss", // type
"instance": "env:MISSKEY_INSTANCE", // misskey instance
"token": "env:MISSKEY_TOKEN", // access token with the `View your account information` scope
"options": {
"allowed_visibility": [
"public",
"home"
]
}
}
Misskey API is not very good, this also wasn't tested on vanilla misskey.
confirmed supported:
- Sharkey
Outputs#
Mastodon API#
no remarks.
{
"type": "mastodon",
"token": "env:MASTODON_TOKEN", // Must be a mastodon token. get from something like phanpy + webtools. or https://getauth.thms.uk/?client_name=xpost&scopes=read%20write%20profile but doesn't work with all software
"instance": "env:MASTODON_INSTNACE", // mastodon api compatible instance
"options": {
"visibility": "public"
}
}
Bluesky#
in the bluesky block, you can configure who is allowed to reply to and quote the new posts. handle becomes optional if you specify a DID.
{
"type": "bluesky", // type
"handle": "env:BLUESKY_HANDLE", // handle (e.g. melontini.me)
"app_password": "env:BLUESKY_APP_PASSWORD", // https://bsky.app/settings/app-passwords
"did": "env:BLUESKY_DID", // use a DID instead of handle (avoids handle resolution)
"pds": "env:BLUESKY_PDS", // specify Your PDS directly (avoids DID doc lookup)
"bsky_appview": "env:BLUESKY_APPVIEW", // bypass suspensions by specifying a different appview (e.g. did:web:bsky.zeppelin.social)
"options": {
"encode_videos": true, // bluesky only accepts mp4 videos, try to convert if the video is not mp4
"quote_gate": false, // block users from quoting the post
"thread_gate": [ // block replies. leave empty to disable replies
"mentioned",
"following",
"followers",
"everybody" // allow everybody to reply (ignores other options)
]
}
}