Ruby CLI tool for accessing Bluesky API / ATProto
Ruby 98.6%
Shell 1.4%
10 1 3

Clone this repository

https://tangled.org/mackuba.eu/ratproto
git@tangled.org:mackuba.eu/ratproto

For self-hosted knots, clone URLs may differ based on your setup.

README.md

RatProto – Ruby ATProto Tool 🐀#

RatProto (rat) is a small command-line tool in Ruby for accessing the Bluesky API / AT Protocol.

It builds on top of the existing ATProto Ruby gems:

  • minisky — XRPC client
  • skyfall — firehose & Jetstream streaming
  • didkit — DID & handle resolution
NOTE

Part of ATProto Ruby SDK: ruby.sdk.blue

Installation#

To run this tool, you need some reasonably recent version of Ruby installed – it should run on Ruby 2.6 and above, although it's recommended to use a version that still gets maintainance updates, i.e. currently 3.2+.

An older version of Ruby (2.6.x) that should work is shipped with macOS versions 11.0 or later, a recent version of Ruby is also likely to be already installed on most Linux systems, or at least available through the OS's package manager. More installation options can be found on ruby-lang.org.

To install rat, run:

[sudo] gem install ratproto

Features#

Currently implemented features/commands:

  • resolving DIDs & handles (rat resolve)
  • fetching & printing ATProto records (rat fetch)
  • streaming firehose / Jetstream events with optional filters (rat stream)

Resolving a DID or handle#

rat resolve <did>|<handle>

Pass a DID or a handle (@ optional) to look up the given account's identity & print the DID document:

$ rat resolve atproto.com

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/multikey/v1",
    "https://w3id.org/security/suites/secp256k1-2019/v1"
  ],
  "id": "did:plc:ewvi7nxzyoun6zhxrhs64oiz",
  "alsoKnownAs": [
    "at://atproto.com"
  ],
  "verificationMethod": [
    {
      "id": "did:plc:ewvi7nxzyoun6zhxrhs64oiz#atproto",
      "type": "Multikey",
      "controller": "did:plc:ewvi7nxzyoun6zhxrhs64oiz",
      "publicKeyMultibase": "zQ3shunBKsXixLxKtC5qeSG9E4J5RkGN57im31pcTzbNQnm5w"
    }
  ],
  "service": [
    {
      "id": "#atproto_pds",
      "type": "AtprotoPersonalDataServer",
      "serviceEndpoint": "https://enoki.us-east.host.bsky.network"
    }
  ]
}

Fetching a record#

rat fetch at://<did>/<collection>/<rkey>

Pass an at:// URI as the argument to fetch a single record from the user’s PDS:

% rat fetch at://did:plc:ragtjsm2j2vknwkz3zp4oxrd/app.bsky.feed.post/3lxxmboqmf22j

{
  "text": "a gatinha gorda",
  "$type": "app.bsky.feed.post",
  "embed": {
    "$type": "app.bsky.embed.images",
    "images": [
      {
        "alt": "Kit lying on the ground under the chair ",
        "image": {
          "$type": "blob",
          "ref": {
            "$link": "bafkreiebzsetrrvymvq6dvwma77zqprnv73ovgeqilanzi453dm6xart4q"
          },
          "mimeType": "image/jpeg",
          "size": 963750
        },
        "aspectRatio": {
          "width": 2000,
          "height": 1500
        }
      }
    ]
  },
  "langs": [
    "en"
  ],
  "createdAt": "2025-09-03T21:48:05.910Z"
}

Streaming commit events#

rat stream <firehose-host> [-j] [-r cursor] [-c collections] [-d dids]

Rat can connect to either a relay/PDS firehose:

rat stream bsky.network

or a Jetstream service (use -j):

rat stream -j jetstream2.us-east.bsky.network

You can also pass a cursor to connect with using -r / --cursor (tip: pass -r0 to rewind as far back as the buffer allows).

Once connected, you’ll see output like:

[2025-01-02T12:34:56+01:00] did:plc:xwnehmdpjluz2kv3oh2mfi47 :create app.bsky.feed.post 3mbjs5rgtin2z {"text":"hi", ...}
[2025-01-02T12:34:57+01:00] did:plc:3mfkuhmjxd2wvz2e7nhl4poi :delete app.bsky.graph.follow 3mbjs5rghri23

Press Ctrl-C to disconnect.

You can also apply the filtering options below (for Jetstream, these are passed to the server to apply filtering server-side via wantedCollections / wantedDids parameters):

Filtering by DID#

To print only events from given DID(s):

rat stream bsky.network -d did:plc:abcd1234,did:plc:xyz9999,...

You can either pass a comma-separated list as one parameter, or repeat -d val more than once.

Filtering by collection#

To print only records from given collection(s):

rat stream bsky.network -c app.bsky.feed.post -c app.bsky.actor.profile

Credits#

Copyright © 2026 Kuba Suder (@mackuba.eu).

The code is available under the terms of the zlib license (permissive, similar to MIT).

Bug reports and pull requests are welcome 😎