A bot that listens for /post commands in a Signal group and automatically posts the message to Bluesky.
- Listens to a specific Signal group for
/postcommands - Automatically posts the message content to Bluesky
- Provides feedback in the Signal group about posting status
- Full error handling and logging
- Python 3.8+
uvpackage managersignal-cliinstalled and configured- Bluesky account with app password
- Install dependencies:
uv sync- Create a
.envfile with your configuration:
BSKY_USER=your-handle.bsky.social
BSKY_PASS=your-app-password
SIGNAL_ACCOUNT=+1234567890
SIGNAL_SOCKET_PATH=/run/user/1000/signal-cli/socket
SIGNAL_GROUP=your-group-id-here- Go to Bluesky Settings → App Passwords
- Create a new app password
- Use your handle (e.g.,
username.bsky.social) and the app password in the.envfile
- Install and configure
signal-cli - Start the signal-cli daemon:
signal-cli -a +1234567890 daemon --socket- Get your group ID by monitoring signal-cli output or using the listGroups command
You can configure a list of words to be automatically removed from any text before it is posted to Bluesky (and from the Signal preview description).
- Env var:
REDACT_WORDS - Format: comma-separated values (CSV)
- Matching: case-insensitive, substring removal
Example .env line:
REDACT_WORDS=alice,charlie,projectxIf omitted, no redaction is performed.
The easiest way to run the bot is using Docker with the provided justfile commands:
# Build and start the bot
just build
just up
# View logs
just logs
# Stop the bot
just down
# Restart the bot
just restartThe bot will automatically restart unless manually stopped, so you can just set it and forget it.
Use just to see all available commands:
just # Show all commands
just build # Build the Docker image
just up # Start the bot (detached)
just down # Stop the bot
just logs # View live logs
just status # Check bot status
just restart # Restart the bot
just rebuild # Rebuild and restart
just check-signal # Verify signal-cli socket
just clean # Clean up containers# Normal mode
uv run python bot.py
# Debug mode (verbose logging)
uv run python bot.py --debugIn your Signal group, send a message starting with /post followed by the text you want to post to Bluesky:
/post Hello world! This will be posted to Bluesky.
The bot will:
- Detect the
/postcommand - Post the text to Bluesky
- Reply in Signal with only the Bluesky post URL (and a rich preview)
You can also reply with /post to any message in the group. If your /post message includes a quote (i.e., you replied to a message), the bot will ignore any text typed after /post and will post the quoted message's text instead.
/post Just deployed a new feature! 🚀
/post Check out this cool project I'm working on:
https://github.com/username/project
/post Multi-line posts work too!
This is the second line.
And this is the third.
# Replying to a message with /post (quote handling)
# The bot will post the quoted message text, ignoring any inline text you add
# Example usage in Signal:
# 1) Reply to a message with just: /post
# 2) Reply to a message with: /post ignore this text
# In both cases, the quoted message content will be posted.
Run the test suite to verify the bot logic:
uv run python test_bot.pyThe bot provides comprehensive logging:
- Info level: Shows successful operations and status updates
- Debug level: Shows detailed message parsing and API calls
- Error level: Shows failures and exceptions
- Keep your
.envfile secure and never commit it to version control - Use Bluesky app passwords instead of your main account password
- The bot only listens to the specific Signal group configured in
SIGNAL_GROUP
- Make sure
signal-clidaemon is running - Check that the socket path in
.envmatches your system - Verify the Signal account number is correct
- Verify your Bluesky handle and app password are correct
- Check that your Bluesky account is in good standing
- Try creating a new app password
- Check that the message is sent in the correct Signal group
- Verify the group ID in your
.envfile - Run with
--debugto see detailed message parsing logs