A simple tool which lets you scrape twitter accounts and crosspost them to bluesky accounts! Comes with a CLI and a webapp for managing profiles! Works with images/videos/link embeds/threads.
···1-# Tweets to Bluesky Crossposter
23-A powerful, set-and-forget tool to mirror your Twitter/X account to Bluesky.
45-> **Credits:** This project is powered by [bird](https://github.com/steipete/bird) by [steipete](https://github.com/steipete) for robust Twitter/X data fetching.
67-## Why this tool?
00000089-Most crossposters are either paid services or lack key features. This tool is designed for power users who want a perfect mirror:
1011-* **Smart Media Handling:**
12- * **Videos:** Downloads videos from Twitter and uploads them natively to Bluesky (up to 100MB).
13- * **Images:** Uploads high-resolution images with the **correct aspect ratio** (no weird cropping).
14- * **Links:** Automatically removes `t.co` tracking links and expands them to their real destinations.
15-* **Smart Features:**
16- * **Language Detection:** Automatically detects the language of your tweet (e.g., English, Japanese) and tags the Bluesky post correctly.
17- * **Human-like Pacing:** Randomly waits (1-4s) between posts to behave more like a real user and avoid spam detection.
18- * **Auto-Healing:** Automatically rotates internal Twitter Query IDs if they expire, ensuring the tool keeps working 24/7 without manual intervention.
19-* **Threads & Replies:**
20- * **Perfect Threading:** If you write a thread (reply to yourself) on Twitter, it appears as a threaded conversation on Bluesky.
21- * **Clean Feed:** Automatically filters out your replies to *other* people, keeping your Bluesky timeline focused on your original content.
22- * **Quotes:** Smartly handles Quote Tweets, embedding the quoted post if available.
23-* **History Import:**
24- * Backfill your entire tweet history chronologically (Oldest → Newest).
25- * Preserves original timestamps on posts.
26- * Uses human-like pacing to avoid rate limits.
27-* **Safety:**
28- * Designed to use **Alt Account Cookies**. You can use a burner account to fetch tweets, protecting your main account from suspension risks.
2930-## Setup
31-32-### 1. Installation
0330034```bash
35git clone https://github.com/j4ckxyz/tweets-2-bsky.git
36cd tweets-2-bsky
37npm install
38```
3940-### 2. Configuration (`.env`)
00004142-Create a `.env` file in the project folder:
00043044```bash
45-# --- Twitter Configuration ---
46-# 1. Log in to x.com (RECOMMENDED: Use a separate "burner" account!)
47-# 2. Open Developer Tools (F12) -> Application -> Cookies
48-# 3. Copy the values for 'auth_token' and 'ct0'
49-TWITTER_AUTH_TOKEN=d03...
50-TWITTER_CT0=e1a...
5152-# The username of the account you want to MIRROR (e.g., your main account)
53-# If left empty, it tries to mirror the account you logged in with (NOT RECOMMENDED).
54-TWITTER_TARGET_USERNAME=jack
55-56-# --- Bluesky Configuration ---
57-BLUESKY_IDENTIFIER=jack.bsky.social
58-# Generate an App Password in Bluesky Settings -> Privacy & Security
59-BLUESKY_PASSWORD=xxxx-xxxx-xxxx-xxxx
60-61-# --- Optional ---
62-CHECK_INTERVAL_MINUTES=5
63-# BLUESKY_SERVICE_URL=https://bsky.social (Change for custom PDS)
64```
6566-**⚠️ Safety Tip:**
67-Twitter is strict about scraping. **Do not use your main account's cookies.**
68-1. Create a fresh Twitter account (or use an old alt).
69-2. Log in with that alt account in your browser.
70-3. Grab the cookies (`auth_token`, `ct0`) from that alt account.
71-4. Set `TWITTER_TARGET_USERNAME` to your **main** account's handle (e.g., `elonmusk`).
72-The tool will use the alt account to "view" your main account's profile and copy the tweets.
7374-### 3. Usage
7576-**Development (with hot reload):**
077```bash
78-npm run dev
000079```
8081-**Production:**
082```bash
83-npm run build
84-npm start
85```
8687-**Import History:**
88-Migrate your old tweets. This runs once and stops.
89```bash
90-npm run import
0091```
9293-### 4. Other Commands
94-95-| Command | Description |
96-|---------|-------------|
97-| `npm run build` | Compile TypeScript to `dist/` |
98-| `npm run dev` | Run directly with tsx (no build needed) |
99-| `npm run lint` | Run Biome linter with auto-fix |
100-| `npm run format` | Format code with Biome |
101-| `npm run typecheck` | Type-check without emitting |
102103-## Running on a Server (VPS)
104105-To keep this running 24/7 on a Linux server (e.g., Ubuntu):
00106107-1. **Build the project:**
108- ```bash
109- npm run build
110- ```
111-2. **Install PM2 (Process Manager):**
112- ```bash
113- sudo npm install -g pm2
114- ```
115-3. **Start the tool:**
116- ```bash
117- pm2 start dist/index.js --name "twitter-mirror"
118- ```
119-4. **Check logs:**
120- ```bash
121- pm2 logs twitter-mirror
122- ```
123-5. **Enable startup on reboot:**
124- ```bash
125- pm2 startup
126- pm2 save
127- ```
128129-## Tech Stack
130-131-- **TypeScript** – Full type safety
132-- **Biome** – Fast linting & formatting
133-- **tsx** – TypeScript execution for development
···1+# 🐦 Tweets-2-Bsky
23+A powerful tool to crosspost your Tweets to Bluesky automatically. Now supports **multiple accounts**, **custom PDS (hosting) locations**, and a **user-friendly CLI** for easy management.
45+## ✨ Features
67+- **Multi-Account Support**: Sync Twitter A -> Bluesky A, Twitter B -> Bluesky B, or multiple Twitters to one Bluesky.
8+- **Interactive CLI**: Manage all your account mappings and credentials without touching code.
9+- **Custom PDS Support**: Works with `bsky.social` or any independent Bluesky hosting provider.
10+- **Thread Support**: Maintains your Twitter threads perfectly on Bluesky.
11+- **Media Support**: Automatically migrates high-quality images and videos.
12+- **Smart Logic**: Automatically detects languages and expands short links.
13+- **Safety First**: Includes a `--dry-run` mode to test before you post.
1415+---
1617+## 🚀 Quick Start (For Everyone)
000000000000000001819+### 1. Prerequisites
20+- **Node.js** installed on your computer.
21+- A Twitter account (preferably an alt/burner for the web cookies).
22+- A Bluesky account and an **App Password** (Settings -> Privacy & Security -> App Passwords).
2324+### 2. Installation
25+Open your terminal and run:
26```bash
27git clone https://github.com/j4ckxyz/tweets-2-bsky.git
28cd tweets-2-bsky
29npm install
30```
3132+### 3. Setup (Using the CLI)
33+Instead of editing files, use our simple setup command:
34+```bash
35+# 1. Set your Twitter cookies (one set of cookies works for all mappings)
36+npm run cli setup-twitter
3738+# 2. Add your first account mapping
39+npm run cli add-mapping
40+```
41+*Note: You can find your Twitter `auth_token` and `ct0` in your browser's developer tools under Application -> Cookies.*
4243+### 4. Run the Sync
44```bash
45+# Build the project
46+npm run build
00004748+# Start the automatic syncing daemon
49+npm start
000000000050```
5152+---
0000005354+## 🛠 Advanced Usage
5556+### Backfilling Old Tweets
57+If you want to import your historical tweets for a specific account:
58```bash
59+# Get the command from the CLI help
60+npm run cli import-history
61+62+# Example: Import the last 10 tweets for a specific user
63+npm run import -- --username YOUR_TWITTER_HANDLE --limit 10
64```
6566+### Testing with Dry Run
67+See what would be posted without actually posting anything:
68```bash
69+npm start -- --dry-run
070```
7172+### Management Commands
073```bash
74+npm run cli list # Show all active mappings
75+npm run cli remove # Remove an account mapping
76+npm run cli set-interval # Change how often to check for new tweets
77```
7879+---
000000008081+## 📝 Configuration Details
8283+- **Check Interval**: Default is 5 minutes.
84+- **Database**: Processed tweets are tracked per-account in the `processed/` folder so you never get duplicates.
85+- **Service URL**: If you use a custom Bluesky host (like `bsky.network`), you can set it during the `add-mapping` process.
8687+## ⚖️ License
88+MIT
00000000000000000008990+---
91+*Created with ❤️ for the decentralized web.*000