How to Use the goat CLI to Migrate a Bluesky Account
🔍 WiseChecker

How to Use the goat CLI to Migrate a Bluesky Account

Migrating a Bluesky account to a new handle or a different hosting provider can feel risky because you must transfer your posts, follows, and account settings without losing data. The goat CLI is an open-source command-line tool that automates the entire migration process by reading your existing account and writing it to a new Bluesky account. This article explains how to install the goat CLI, what prerequisites you need, and the exact steps to migrate your account safely. You will also learn how to verify the migration and handle common errors during the transfer.

Key Takeaways: Migrate a Bluesky Account Using goat CLI

  • goat CLI install command: npm install -g @atproto/goat installs the tool globally on your system.
  • goat account migrate command: goat account migrate --from-handle oldhandle.bsky.social --to-handle newhandle.bsky.social transfers posts, follows, and profile data.
  • Manual domain verification step: You must add a TXT DNS record for a custom domain handle before migration completes.

What the goat CLI Does for Bluesky Account Migration

The goat CLI is the official command-line interface for the AT Protocol that Bluesky runs on. It provides a dedicated account migrate subcommand that copies your entire account state from one Bluesky handle to another. The tool transfers your posts, reposts, likes, follows, lists, and profile metadata. It does not transfer direct messages because Bluesky does not store DMs in a portable format yet.

Before you start, you need the following items ready:

  • Node.js version 18 or later installed on Windows, macOS, or Linux.
  • Two Bluesky accounts that both exist and are active. The source account is the one you are leaving. The destination account is the new one that receives the data.
  • App passwords for both accounts. Generate them in Bluesky Settings > App Passwords.
  • DNS control if you are migrating to a custom domain handle. You must add a TXT record to prove domain ownership.

Steps to Install goat CLI and Migrate Your Bluesky Account

The migration process has three phases: installation, migration command execution, and domain verification if applicable. Follow these steps in order.

Phase 1: Install goat CLI on Your Machine

  1. Open your terminal
    On Windows, open Command Prompt or PowerShell as administrator. On macOS or Linux, open Terminal.
  2. Install goat globally
    Type npm install -g @atproto/goat and press Enter. Wait for the installation to finish. You will see a success message when done.
  3. Verify the installation
    Run goat --version. The output shows the version number. If you see an error, ensure Node.js is installed and that npm is in your system PATH.

Phase 2: Run the Migration Command

  1. Generate app passwords for both accounts
    Log in to Bluesky on the web. Go to Settings > App Passwords. Create one app password for the source account and one for the destination account. Copy each password to a secure text file.
  2. Execute the migrate command
    In your terminal, run the following command. Replace the placeholder values with your actual handles and app passwords.

    goat account migrate --from-handle oldhandle.bsky.social --from-password OLD_APP_PASSWORD --to-handle newhandle.bsky.social --to-password NEW_APP_PASSWORD

  3. Wait for the tool to process
    The CLI will display a progress bar. It first reads all records from the source account, then writes them to the destination account. The time depends on the number of posts and follows. A typical account with 5000 posts takes about 10 minutes.
  4. Check the final output
    When finished, you see a summary line that says “Migration complete.” The tool also prints the total number of records transferred.

Phase 3: Verify Domain Handle Ownership (Custom Domain Only)

If your destination handle is a custom domain such as user.example.com, you must verify domain ownership before Bluesky accepts the migrated account. The goat CLI does not do this step automatically.

  1. Add a TXT record to your DNS
    Log in to your domain registrar or DNS hosting provider. Create a TXT record with the name _atproto and the value did=did:plc:YOUR_DESTINATION_DID. You can find the DID in the migration output or by running goat account get --handle newhandle.bsky.social.
  2. Wait for DNS propagation
    DNS changes can take up to 48 hours, but most providers update within 30 minutes. Use a tool like dig _atproto.yourdomain.com TXT to verify the record is visible.
  3. Confirm the handle in Bluesky
    Open Bluesky Settings > Account > Handle. Click “I have my own domain” and enter your custom domain. Bluesky checks the TXT record and activates the handle if the DID matches.

Common Migration Problems and How to Resolve Them

“Account not found” Error When Running the Command

This error means the handle or app password is incorrect. Double-check that you typed the handle exactly, including the .bsky.social suffix or your custom domain. Regenerate the app password if you are unsure it is correct.

Migration Stops at “Reading timeline” and Never Finishes

The goat CLI can hang if the source account has a very large number of records or if Bluesky servers are under load. Press Ctrl+C to cancel the command. Then run the command again with the --resume flag. The tool picks up from where it stopped instead of starting over.

Posts Appear Twice on the Destination Account

This happens when you run the migration command more than once without cleaning the destination account. The tool does not deduplicate records. To fix this, delete the destination account entirely and create a fresh one before re-running the migration.

Custom Domain Handle Shows “Unverified” in Bluesky

The DNS TXT record is either missing, has a typo in the DID value, or has not propagated. Verify the record with a DNS lookup tool. If the record is correct, wait 30 minutes and refresh the Bluesky handle settings page.

goat CLI Migration vs Manual Account Recreation

Item goat CLI Migration Manual Account Recreation
Setup time 10-15 minutes Several hours
Posts transferred All posts including text and embedded media links None unless manually copied
Follows transferred All follow relationships Must refollow each account individually
Lists and feeds All user lists and saved feeds Lost completely
Risk of data loss Low if app passwords are correct High because manual copying is error-prone

You now have a fully migrated Bluesky account with your posts, follows, and profile data intact. To confirm everything is working, log in to the destination account on the Bluesky web app and browse your timeline and profile. For advanced users, the goat CLI also supports the account export command to back up your data as JSON files before migrating. Use goat account export --handle yourhandle.bsky.social --password YOUR_APP_PASSWORD > backup.json to create a local archive you can restore later.