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 ๐Ÿ˜Ž