Skip to content

netarcx/roccobots

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

96 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RoccoBots

An easy way to synchronize posts from 𝕏 (Twitter) to other social media platforms.

Supported Platforms

Platform Notes
☁️ Bluesky Full support: posts, threads, media, quotes, replies, profile sync
🇩 Discord Webhook embeds with engagement stats

Getting Started

The quickest way in is the web dashboard. You configure everything in the browser, so there are no config files to edit by hand. Here's the whole thing start to finish.

Before you begin

You'll need a machine that can run Bun (macOS, Linux, or Windows under WSL). If you'd rather use containers, jump to the Docker section below.

You'll also need a few accounts and credentials:

  • The handle of the X (Twitter) account you want to mirror. Just the public handle, e.g. nasa.
  • An X (Twitter) login for the bot to read tweets with. You enter this once, and every bot shares it.
  • At least one place to post to:
    • For Bluesky, your handle and an app password. Create the app password under Bluesky Settings, App Passwords. Don't use your account password.
    • For Discord, a webhook URL for the target channel. Create it under the channel's Edit, Integrations, Webhooks, New Webhook, then copy the URL.

Walkthrough

Install Bun and grab the code:

# Install Bun (other options at https://bun.sh)
curl -fsSL https://bun.sh/install | bash

git clone https://github.com/netarcx/roccobots.git
cd roccobots
bun install

Pick a dashboard password and start the server with it:

WEB_ADMIN_PASSWORD="pick-a-strong-password" bun run start:web

On the first run, RoccoBots generates an encryption key for your saved credentials and writes it next to the database. That's fine for trying things out. On a real server you should set the key yourself so it survives rebuilds; see Web Environment Variables.

Now open http://localhost:3000 and log in with the password you just set.

Before adding a bot, go to Settings and enter the X (Twitter) login the bot will use to read tweets. You only do this once, and all bots use it.

Then click Add Bot and fill in the form:

  • The source handle (the X account to mirror, without the @).
  • A sync frequency. Thirty minutes is a reasonable starting point.
  • One destination and its credentials (the Bluesky app password or Discord webhook URL from above).

Save the bot, then click Start on its card. New posts from the source account will start showing up on your destination. The Logs page shows what the bot is doing as it runs.

There's a more detailed version of this in the web dashboard guide.


Two Modes

RoccoBots runs in one of two modes. Pick whichever fits how you like to work.

CLI Mode Web Dashboard Mode
Config .env file Browser UI
Multi-bot Numeric suffixes in .env Per-bot in the dashboard
Credentials Plaintext in .env Encrypted in SQLite
Monitoring Terminal logs Live dashboard with log history
Analytics Not available Bluesky engagement stats
Entry point bun src/index.ts bun src/web-index.ts

Web Dashboard Mode

Quick Start

Set the dashboard password and start the server:

WEB_ADMIN_PASSWORD=your_secure_password bun src/web-index.ts
# http://localhost:3000

An encryption key is generated and saved beside the database on the first run. To pin a specific key (needed for reproducible deployments and migrations), generate one and add it to your environment:

bun run generate-key
# copy the printed value into ENCRYPTION_KEY
ENCRYPTION_KEY=<64-character hex string>

Once the server is up, open the dashboard and:

  1. Go to Settings and configure the Twitter login that all bots share.
  2. Click Add Bot, enter the handle to mirror, and set up the destination platforms.
  3. Press Start on the bot card.

Docker (Web Dashboard)

docker-compose.yml, using the pre-built image from the GitHub Container Registry:

services:
  roccobots-web:
    container_name: "roccobots-web"
    image: ghcr.io/netarcx/roccobots:latest
    restart: unless-stopped
    env_file: ".env.web"
    environment:
      - DATABASE_PATH=/data/data.sqlite
    ports:
      - "3000:3000"
    volumes:
      - ./data:/data
    command: ["bun", "./src/web-index.ts"]

.env.web:

WEB_ADMIN_PASSWORD=your_secure_password

# Optional. Pin the encryption key so credentials survive container rebuilds.
# Generate with: bun run generate-key
ENCRYPTION_KEY=your_64_char_hex_key

# Optional
WEB_PORT=3000
DATABASE_PATH=/data/data.sqlite

If you leave ENCRYPTION_KEY unset, a key file is generated at /data/.encryption.key. Mount the /data volume so it persists across restarts. Lose that key and every saved platform credential becomes unreadable.


Web Dashboard Features

Dashboard

  • Bot cards showing status (running, stopped, error), last sync time, and enabled platforms
  • Start and stop individual bots, or all of them at once
  • Import bots from an existing .env file

Adding a Bot

  1. Click Add Bot
  2. Enter the source Twitter handle
  3. Set the sync frequency (default: 30 minutes)
  4. Toggle the sync options you want (posts, bio, profile picture, display name, header)
  5. Add one or more destination platforms and fill in their credentials
  6. Save. Credentials are encrypted at rest with AES-256-GCM.

Settings

  • Twitter Authentication: the single Twitter login all bots use to read tweets
  • Backup & Restore: export or import all bot configs, platform credentials, and sync state as JSON

The backup file contains plaintext credentials, so store it somewhere safe.

Logs

Each bot keeps a paginated log history with timestamps and platform tags (info, warn, error, success). Open it from the bot card or at /bots/:id/logs.

Analytics (Bluesky)

Tracks engagement on posts that have synced to Bluesky.

  1. Open Analytics and select a bot
  2. Click Refresh from Bluesky to pull current like, repost, reply, and quote counts
  3. Posts are ranked by total engagement

Analytics can be turned on or off per bot under Sync Options, Bluesky Analytics.

Text Transforms

Per-bot rules that rewrite post text before it's sent to a platform:

Rule Effect
prepend Add text before every post
append Add text after every post
regex_replace Find and replace with a regular expression
strip_urls Remove URLs matching a pattern
add_hashtags Append hashtags to every post

Rules apply globally or only to specific platforms (Bluesky, for example). Configure them through the API at PUT /api/bots/:id/transforms.

Bluesky Commands

Trusted Bluesky handles can control a bot by mentioning it with a command:

Command Action
!sync Trigger an immediate sync
!restart Restart the bot
!source @handle Change the source Twitter account
!status Report current bot status
!frequency <min> Change the sync interval
!posts on/off Toggle post syncing
!bio on/off Toggle bio syncing
!help List available commands

Turn commands on per bot in the bot edit form under Bluesky Commands, where you also set the trusted handles and the poll interval (default: 60 seconds).


Web Environment Variables

Variable Required Default Description
WEB_ADMIN_PASSWORD Yes none Password for the web dashboard login
ENCRYPTION_KEY No auto-generated 64-char hex key used to encrypt stored credentials
WEB_PORT No 3000 HTTP port the server listens on
DATABASE_PATH No data.sqlite Path to the SQLite database file
LOG_RETENTION_DAYS No 30 How many days of sync logs to keep

CLI Mode

Docker (CLI)

docker-compose.cli.yml, using the pre-built image:

services:
  roccobots:
    container_name: "roccobots"
    image: ghcr.io/netarcx/roccobots:latest
    restart: unless-stopped
    env_file: ".env"
    environment:
      - DATABASE_PATH=/data/data.sqlite
    volumes:
      - ./data:/data

Run it with:

docker compose -f docker-compose.cli.yml up -d

Environment Variables (.env)

Single Account

# X (Twitter)
TWITTER_HANDLE=YourXHandle
TWITTER_USERNAME=your_x_email@example.com
TWITTER_PASSWORD=YourXPassword

# Bluesky (optional)
BLUESKY_INSTANCE=bsky.social          # default: bsky.social
BLUESKY_IDENTIFIER=your-handle.bsky.social
BLUESKY_PASSWORD=xxxx-xxxx-xxxx-xxxx  # use an app password

# Discord webhook (optional)
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/1234567890/abcde

Multi-Account

Each account uses a numeric suffix. The first has no suffix, the second uses 1, the third uses 2, and so on. Accounts can target different platforms.

# ======= ACCOUNT 0 (no suffix) =======
TWITTER_HANDLE=FirstXHandle
BLUESKY_IDENTIFIER=first-handle.bsky.social
BLUESKY_PASSWORD=xxxx-xxxx-xxxx-xxxx
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/111111111/xxxxxxxxxx

# ======= ACCOUNT 1 =======
TWITTER_HANDLE1=SecondXHandle
BLUESKY_IDENTIFIER1=second-handle.bsky.social
BLUESKY_PASSWORD1=yyyy-yyyy-yyyy-yyyy

# ======= ACCOUNT 2 =======
TWITTER_HANDLE2=ThirdXHandle
DISCORD_WEBHOOK_URL2=https://discord.com/api/webhooks/222222222/zzzzzzzzzz

Optional CLI Variables

Variable Default Description
SYNC_FREQUENCY_MIN 30 Minutes between sync cycles
DAEMON true Keep running on a loop. Set to false to run once and exit
SYNC_POSTS true Sync posts
SYNC_PROFILE_DESCRIPTION true Sync bio
SYNC_PROFILE_PICTURE true Sync profile picture
SYNC_PROFILE_NAME true Sync display name
SYNC_PROFILE_HEADER true Sync header image
BACKDATE_BLUESKY_POSTS true Use the original tweet timestamp on Bluesky
DATABASE_PATH data.sqlite Path to the SQLite database
FORCE_SYNC_POSTS false Re-sync already-synced posts

Building from Source

# Install Bun: https://bun.sh
bun install

# CLI mode
bun src/index.ts

# Web dashboard mode
bun src/web-index.ts

Contact

Bluesky: @beastModeRocco.com

About

New and improved Docker container for Twitter to Bluesky bots

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages