Documentation

Configuration

Environment variables, target flags, aliases, and safe validation.

Minimal .env

Start with the example file:

cp .env.example .env

The smallest useful dry-run config is:

BOT_TOKEN=123456789:telegram-secret
AUTHORIZED_TELEGRAM_USERS=your_username
CROSSPOST_FLAGS=-bmt
SHITPOST_DRY_RUN=1

CROSSPOST_FLAGS=-bmt tells crosspost to post to Bluesky, Mastodon, and Twitter/X. Change it to match the destinations you actually configured.

Core variables

VariableRequiredPurpose
BOT_TOKENYesTelegram bot token from BotFather.
AUTHORIZED_TELEGRAM_USERSRecommendedComma-separated usernames or numeric IDs allowed to use the bot. Empty means public.
CROSSPOST_FLAGSNoFlags passed directly to crosspost; defaults to -bmt.
SHITPOST_DRY_RUNNoSet to 1, true, or yes to preview commands without posting.
CROSSPOST_REPONoSource repo used when building the Docker image.
CROSSPOST_REFNoBranch, tag, or ref used when building the Docker image.

Platform variables

VariablePlatformPurpose
BLUESKY_HOSTBlueskyUsually bsky.social.
BLUESKY_IDENTIFIERBlueskyHandle or email.
BLUESKY_PASSWORDBlueskyApp password.
MASTODON_HOSTMastodonInstance URL, such as https://mastodon.social.
MASTODON_ACCESS_TOKENMastodonAccess token with posting permission.
MASTODON_CLIENT_KEYMastodonOptional client key for crosspost flows that need it.
MASTODON_CLIENT_SECRETMastodonOptional client secret for crosspost flows that need it.
AUTH_TOKENXAlias for the X auth_token cookie.
TWITTER_AUTH_TOKENXExplicit X auth_token; overrides AUTH_TOKEN.
TWITTER_AUTH_CLIENTXOptional client identity understood by the emusks-backed strategy.
TWITTER_GRAPHQL_ENDPOINTXOptional endpoint profile understood by the emusks-backed strategy.
TWITTER_PROXYXOptional proxy for X requests.
TWITTER_API_CONSUMER_KEYXOfficial API consumer key fallback.
TWITTER_API_CONSUMER_SECRETXOfficial API consumer secret fallback.
TWITTER_ACCESS_TOKEN_KEYXOfficial API access token fallback.
TWITTER_ACCESS_TOKEN_SECRETXOfficial API access token secret fallback.

Alias normalization

Before shitpost starts crosspost, it copies legacy aliases into the variable names crosspost expects when the target variable is empty.

TargetAccepted aliases
TWITTER_AUTH_TOKENAUTH_TOKEN
TWITTER_API_CONSUMER_KEYconsumer_key, TWITTER_CONSUMER_KEY
TWITTER_API_CONSUMER_SECRETconsumer_key_secret, TWITTER_CONSUMER_SECRET
TWITTER_ACCESS_TOKEN_KEYaccess_token, access_token_key, TWITTER_ACCESS_TOKEN
TWITTER_ACCESS_TOKEN_SECRETaccess_token_secret, TWITTER_ACCESS_SECRET

Validate without leaking secrets

Run the doctor task when posts fail or before deploying a new .env:

task doctor

The doctor script prints whether each key is present and the value length. It does not print secret values.

SHITPOST_DRY_RUN=1
CROSSPOST_FLAGS=-bmt

Send one text message and one image with a caption. If the Telegram replies show the expected command, set SHITPOST_DRY_RUN=0 and restart the service.