Ruby CLI tool for accessing Bluesky API / ATProto
1# RatProto – Ruby ATProto Tool 🐀 2 3RatProto (`rat`) is a small command-line tool in Ruby for accessing the Bluesky API / AT Protocol. 4 5It builds on top of the existing ATProto Ruby gems: 6 7- [`minisky`](https://tangled.org/mackuba.eu/minisky/) — XRPC client 8- [`skyfall`](https://tangled.org/mackuba.eu/skyfall/) — firehose & Jetstream streaming 9- [`didkit`](https://tangled.org/mackuba.eu/didkit/) — DID & handle resolution 10 11> [!NOTE] 12> Part of ATProto Ruby SDK: [ruby.sdk.blue](https://ruby.sdk.blue) 13 14 15## Installation 16 17To 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+. 18 19An 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](https://www.ruby-lang.org/en/downloads/). 20 21To install `rat`, run: 22 23``` 24[sudo] gem install ratproto 25``` 26 27## Features 28 29Currently implemented features/commands: 30 31- resolving DIDs & handles (`rat resolve`) 32- fetching & printing ATProto records (`rat fetch`) 33- streaming firehose / Jetstream events with optional filters (`rat stream`) 34 35 36## Resolving a DID or handle 37 38``` 39rat resolve <did>|<handle> 40``` 41 42Pass a DID or a handle (@ optional) to look up the given account's identity & print the DID document: 43 44``` 45$ rat resolve atproto.com 46 47{ 48 "@context": [ 49 "https://www.w3.org/ns/did/v1", 50 "https://w3id.org/security/multikey/v1", 51 "https://w3id.org/security/suites/secp256k1-2019/v1" 52 ], 53 "id": "did:plc:ewvi7nxzyoun6zhxrhs64oiz", 54 "alsoKnownAs": [ 55 "at://atproto.com" 56 ], 57 "verificationMethod": [ 58 { 59 "id": "did:plc:ewvi7nxzyoun6zhxrhs64oiz#atproto", 60 "type": "Multikey", 61 "controller": "did:plc:ewvi7nxzyoun6zhxrhs64oiz", 62 "publicKeyMultibase": "zQ3shunBKsXixLxKtC5qeSG9E4J5RkGN57im31pcTzbNQnm5w" 63 } 64 ], 65 "service": [ 66 { 67 "id": "#atproto_pds", 68 "type": "AtprotoPersonalDataServer", 69 "serviceEndpoint": "https://enoki.us-east.host.bsky.network" 70 } 71 ] 72} 73``` 74 75 76## Fetching a record 77 78``` 79rat fetch at://<did>/<collection>/<rkey> 80``` 81 82Pass an at:// URI as the argument to fetch a single record from the user’s PDS: 83 84``` 85% rat fetch at://did:plc:ragtjsm2j2vknwkz3zp4oxrd/app.bsky.feed.post/3lxxmboqmf22j 86 87{ 88 "text": "a gatinha gorda", 89 "$type": "app.bsky.feed.post", 90 "embed": { 91 "$type": "app.bsky.embed.images", 92 "images": [ 93 { 94 "alt": "Kit lying on the ground under the chair ", 95 "image": { 96 "$type": "blob", 97 "ref": { 98 "$link": "bafkreiebzsetrrvymvq6dvwma77zqprnv73ovgeqilanzi453dm6xart4q" 99 }, 100 "mimeType": "image/jpeg", 101 "size": 963750 102 }, 103 "aspectRatio": { 104 "width": 2000, 105 "height": 1500 106 } 107 } 108 ] 109 }, 110 "langs": [ 111 "en" 112 ], 113 "createdAt": "2025-09-03T21:48:05.910Z" 114} 115``` 116 117## Streaming commit events 118 119``` 120rat stream <firehose-host> [-j] [-r cursor] [-c collections] [-d dids] 121``` 122 123Rat can connect to either a relay/PDS firehose: 124 125``` 126rat stream bsky.network 127``` 128 129or a Jetstream service (use `-j`): 130 131``` 132rat stream -j jetstream2.us-east.bsky.network 133``` 134 135You can also pass a cursor to connect with using `-r` / `--cursor` (tip: pass `-r0` to rewind as far back as the buffer allows). 136 137Once connected, you’ll see output like: 138 139``` 140[2025-01-02T12:34:56+01:00] did:plc:xwnehmdpjluz2kv3oh2mfi47 :create app.bsky.feed.post 3mbjs5rgtin2z {"text":"hi", ...} 141[2025-01-02T12:34:57+01:00] did:plc:3mfkuhmjxd2wvz2e7nhl4poi :delete app.bsky.graph.follow 3mbjs5rghri23 142``` 143 144Press Ctrl-C to disconnect. 145 146You can also apply the filtering options below (for Jetstream, these are passed to the server to apply filtering server-side via `wantedCollections` / `wantedDids` parameters): 147 148 149### Filtering by DID 150 151To print only events from given DID(s): 152 153``` 154rat stream bsky.network -d did:plc:abcd1234,did:plc:xyz9999,... 155``` 156 157You can either pass a comma-separated list as one parameter, or repeat `-d val` more than once. 158 159 160### Filtering by collection 161 162To print only records from given collection(s): 163 164``` 165rat stream bsky.network -c app.bsky.feed.post -c app.bsky.actor.profile 166``` 167 168 169## Credits 170 171Copyright © 2026 Kuba Suder ([@mackuba.eu](https://bsky.app/profile/did:plc:oio4hkxaop4ao4wz2pp3f4cr)). 172 173The code is available under the terms of the [zlib license](https://choosealicense.com/licenses/zlib/) (permissive, similar to MIT). 174 175Bug reports and pull requests are welcome 😎