{"id":49532498,"url":"https://github.com/netarcx/roccobots","last_synced_at":"2026-05-02T08:34:30.908Z","repository":{"id":324642387,"uuid":"1096780016","full_name":"netarcx/roccobots","owner":"netarcx","description":"New and improved Docker container for Twitter to Bluesky bots ","archived":false,"fork":false,"pushed_at":"2026-04-23T04:05:17.000Z","size":2549,"stargazers_count":2,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-23T05:13:24.187Z","etag":null,"topics":["bluesky","bot","docker","twitter","updated-endpoints"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/netarcx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-14T23:56:03.000Z","updated_at":"2026-04-23T04:05:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/netarcx/roccobots","commit_stats":null,"previous_names":["netarcx/roccobots"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/netarcx/roccobots","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netarcx%2Froccobots","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netarcx%2Froccobots/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netarcx%2Froccobots/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netarcx%2Froccobots/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/netarcx","download_url":"https://codeload.github.com/netarcx/roccobots/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netarcx%2Froccobots/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32528337,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-02T01:12:54.858Z","status":"online","status_checked_at":"2026-05-02T02:00:05.923Z","response_time":132,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bluesky","bot","docker","twitter","updated-endpoints"],"created_at":"2026-05-02T08:34:29.578Z","updated_at":"2026-05-02T08:34:30.900Z","avatar_url":"https://github.com/netarcx.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RoccoBots\n\nAn easy way to synchronize posts from 𝕏 (Twitter) to other social media platforms.\n\n## Supported Platforms\n\n| Platform | Notes |\n|----------|-------|\n| ☁️ [Bluesky](https://bsky.app/) | Full support: posts, threads, media, quotes, replies, profile sync |\n| 🦣 [Mastodon](https://joinmastodon.org/) | Full support: posts, threads, media, profile sync |\n| Ⓜ️ [Misskey](https://misskey-hub.net/) | Posts with media |\n| 🇩 [Discord](https://discord.com/) | Webhook embeds with engagement stats |\n\n---\n\n## Two Modes\n\nRoccoBots has two operating modes. Choose the one that fits your setup.\n\n| | CLI Mode | Web Dashboard Mode |\n|--|----------|--------------------|\n| **Config** | `.env` file | Browser UI |\n| **Multi-bot** | Numeric suffixes in `.env` | Per-bot in the dashboard |\n| **Credentials** | Plaintext in `.env` | Encrypted in SQLite |\n| **Monitoring** | Terminal logs | Live dashboard with log history |\n| **Analytics** | — | Bluesky engagement stats |\n| **Entry point** | `bun src/index.ts` | `bun src/web-index.ts` |\n\n---\n\n## Web Dashboard Mode\n\n### Quick Start\n\n**1. Set required environment variables**\n\n```bash\nWEB_ADMIN_PASSWORD=your_secure_password\n```\n\nAn encryption key is auto-generated and saved beside the database on first run. To pin a specific key (required for reproducible deployments / migrations):\n\n```bash\n# Generate a key\nbun run generate-key\n\n# Then add the output to your environment:\nENCRYPTION_KEY=\u003c64-character hex string\u003e\n```\n\n**2. Run**\n\n```bash\nbun src/web-index.ts\n# → http://localhost:3000\n```\n\n**3. Open the dashboard and:**\n- Go to **Settings** → configure your Twitter login credentials (shared by all bots)\n- Click **Add Bot** → enter the Twitter handle to mirror and set up destination platforms\n- Hit **Start** on the bot card\n\n---\n\n### Docker — Web Dashboard\n\n`docker-compose.yml` (pre-built image from GitHub Container Registry):\n\n```yaml\nservices:\n  roccobots-web:\n    container_name: \"roccobots-web\"\n    image: ghcr.io/netarcx/roccobots:latest\n    restart: unless-stopped\n    env_file: \".env.web\"\n    environment:\n      - DATABASE_PATH=/data/data.sqlite\n    ports:\n      - \"3000:3000\"\n    volumes:\n      - ./data:/data\n    command: [\"bun\", \"./src/web-index.ts\"]\n```\n\n`.env.web`:\n\n```bash\nWEB_ADMIN_PASSWORD=your_secure_password\n\n# Optional — pin the encryption key so credentials survive container rebuilds.\n# Generate with: bun run generate-key\nENCRYPTION_KEY=your_64_char_hex_key\n\n# Optional\nWEB_PORT=3000\nDATABASE_PATH=/data/data.sqlite\n```\n\n\u003e **Important:** if you don't set `ENCRYPTION_KEY`, a key file is auto-generated at `/data/.encryption.key`. Mount the `/data` volume to persist it across restarts. Without it, all saved platform credentials will be unreadable after a restart.\n\n---\n\n### Web Dashboard Features\n\n#### Dashboard\n\n- Bot cards showing status (running / stopped / error), last sync time, and enabled platforms\n- Start / Stop individual bots or all bots at once\n- Import bots from an existing `.env` file\n\n#### Adding a Bot\n\n1. Click **Add Bot**\n2. Enter the source Twitter handle\n3. Set sync frequency (default: 30 minutes)\n4. Toggle individual sync options (posts, bio, profile picture, display name, header)\n5. Add one or more destination platforms and fill in their credentials\n6. Save — credentials are encrypted at rest with AES-256-GCM\n\n#### Settings\n\n- **Twitter Authentication** — one shared Twitter login used by all bots to read tweets\n- **Backup \u0026 Restore** — export/import all bot configs, platform credentials, and sync state as JSON\n\n\u003e The backup file contains plaintext credentials. Store it securely.\n\n#### Logs\n\nEach bot has a paginated log history (info / warn / error / success entries with timestamps and platform tags). Access from the bot card or via `/bots/:id/logs`.\n\n#### Analytics (Bluesky)\n\nTrack engagement on posts that have been synced to Bluesky.\n\n1. Go to **Analytics**, select a bot\n2. Click **Refresh from Bluesky** to fetch current like / repost / reply / quote counts\n3. Posts are ranked by total engagement\n\nEnable or disable analytics per-bot in the bot's settings under **Sync Options → Bluesky Analytics**.\n\n#### Text Transforms\n\nPer-bot rules that rewrite post text before it is sent to each platform. Available rule types:\n\n| Rule | Effect |\n|------|--------|\n| `prepend` | Add text before every post |\n| `append` | Add text after every post |\n| `regex_replace` | Find/replace using a regular expression |\n| `strip_urls` | Remove URLs matching a pattern |\n| `add_hashtags` | Append hashtags to every post |\n\nRules can be scoped to specific platforms (e.g., Bluesky only) or applied globally. Configure via the API at `PUT /api/bots/:id/transforms`.\n\n#### Bluesky Commands\n\nAllow trusted Bluesky handles to control a bot by mentioning it with a command:\n\n| Command | Action |\n|---------|--------|\n| `!sync` | Trigger an immediate sync |\n| `!restart` | Restart the bot |\n| `!source @handle` | Change the source Twitter account |\n| `!status` | Report current bot status |\n| `!frequency \u003cmin\u003e` | Change sync interval |\n| `!posts on/off` | Toggle post syncing |\n| `!bio on/off` | Toggle bio syncing |\n| `!help` | List available commands |\n\nEnable commands per-bot in the bot edit form under **Bluesky Commands**. Set trusted handles and a poll interval (default: 60 seconds).\n\n---\n\n### Web Environment Variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `WEB_ADMIN_PASSWORD` | ✅ | — | Password for the web dashboard login |\n| `ENCRYPTION_KEY` | — | auto-generated | 64-char hex key used to encrypt stored credentials |\n| `WEB_PORT` | — | `3000` | HTTP port the server listens on |\n| `DATABASE_PATH` | — | `data.sqlite` | Path to the SQLite database file |\n| `LOG_RETENTION_DAYS` | — | `30` | How many days of sync logs to keep |\n\n---\n\n## CLI Mode\n\n### Docker — CLI\n\n`docker-compose.cli.yml` (pre-built image):\n\n```yaml\nservices:\n  roccobots:\n    container_name: \"roccobots\"\n    image: ghcr.io/netarcx/roccobots:latest\n    restart: unless-stopped\n    env_file: \".env\"\n    environment:\n      - DATABASE_PATH=/data/data.sqlite\n    volumes:\n      - ./data:/data\n```\n\nRun with:\n```bash\ndocker compose -f docker-compose.cli.yml up -d\n```\n\n---\n\n### Environment Variables `(.env)`\n\n#### Single Account\n\n```bash\n# --- 𝕏 (Twitter) ---\nTWITTER_HANDLE=YourXHandle\nTWITTER_USERNAME=your_x_email@example.com\nTWITTER_PASSWORD=YourXPassword\n\n# --- ☁️ Bluesky (optional) ---\nBLUESKY_INSTANCE=bsky.social          # default: bsky.social\nBLUESKY_IDENTIFIER=your-handle.bsky.social\nBLUESKY_PASSWORD=xxxx-xxxx-xxxx-xxxx  # use an app password\n\n# --- 🦣 Mastodon (optional) ---\nMASTODON_INSTANCE=https://mastodon.social\nMASTODON_ACCESS_TOKEN=YourMastodonAccessToken\n\n# --- Ⓜ️ Misskey (optional) ---\nMISSKEY_INSTANCE=https://misskey.io\nMISSKEY_ACCESS_CODE=YourMisskeyApiToken\n\n# --- 🇩 Discord Webhook (optional) ---\nDISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/1234567890/abcde\n```\n\n#### Multi-Account\n\nEach account uses a numeric suffix. The first account has no suffix, the second uses `1`, the third uses `2`, and so on. Each account can target different platforms.\n\n```bash\n# ======= ACCOUNT 0 (no suffix) =======\nTWITTER_HANDLE=FirstXHandle\nBLUESKY_IDENTIFIER=first-handle.bsky.social\nBLUESKY_PASSWORD=xxxx-xxxx-xxxx-xxxx\nDISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/111111111/xxxxxxxxxx\n\n# ======= ACCOUNT 1 =======\nTWITTER_HANDLE1=SecondXHandle\nMASTODON_ACCESS_TOKEN1=yyyyyyyyyyyyyyyyyy   # defaults to mastodon.social\n\n# ======= ACCOUNT 2 =======\nTWITTER_HANDLE2=ThirdXHandle\nMISSKEY_INSTANCE2=https://misskey.io\nMISSKEY_ACCESS_CODE2=zzzzzzzzzzzzzzzzzzzzzz\n```\n\n#### Optional CLI Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `SYNC_FREQUENCY_MIN` | `30` | Minutes between sync cycles |\n| `DAEMON` | `true` | Keep running on a loop; `false` = run once and exit |\n| `SYNC_POSTS` | `true` | Sync posts |\n| `SYNC_PROFILE_DESCRIPTION` | `true` | Sync bio |\n| `SYNC_PROFILE_PICTURE` | `true` | Sync profile picture |\n| `SYNC_PROFILE_NAME` | `true` | Sync display name |\n| `SYNC_PROFILE_HEADER` | `true` | Sync header image |\n| `BACKDATE_BLUESKY_POSTS` | `true` | Use original tweet timestamp on Bluesky |\n| `DATABASE_PATH` | `data.sqlite` | Path to the SQLite database |\n| `FORCE_SYNC_POSTS` | `false` | Re-sync already-synced posts |\n\n---\n\n## Building from Source\n\n```bash\n# Install Bun: https://bun.sh\nbun install\n\n# CLI mode\nbun src/index.ts\n\n# Web dashboard mode\nbun src/web-index.ts\n```\n\n---\n\n## Contact\n\nBluesky: [@beastModeRocco.com](https://bsky.app/profile/beastModeRocco.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetarcx%2Froccobots","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnetarcx%2Froccobots","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetarcx%2Froccobots/lists"}