pdsx can read public records from any repository without authentication using the -r flag.
basic usage
read with handle
pdsx -r zzstoatzz.io ls app.bsky.feed.post --limit 5
pdsx automatically discovers the correct PDS:
- handle → DID (via DNS TXT or HTTPS well-known)
- DID → PDS URL (from DID document)
- fetches records from correct PDS
automatic PDS discovery works for any handle or DID, including custom PDS instances. no manual configuration needed!
read with DID (more durable)
pdsx -r did:plc:44ybard66vv44zksje25o7dz ls app.bsky.feed.post --limit 5
DIDs are permanent identifiers - they don’t change if user updates their handle.
handles vs DIDs
handles can change or be reassigned. DIDs are permanent. use DIDs for automation or long-term references.
# first page
pdsx -r zzstoatzz.io ls app.bsky.feed.post --limit 10
# next page cursor: 3lyqmkpiprs2w
# next page
pdsx -r zzstoatzz.io ls app.bsky.feed.post --limit 10 --cursor 3lyqmkpiprs2w
cursors are opaque tokens. for json/yaml output, they go to stderr to avoid breaking parsing. for compact/table output, they appear after results. both humans and LLMs can copy the cursor value for the next command.
# json (for jq pipelines)
pdsx -r zzstoatzz.io ls app.bsky.feed.post -o json | jq -r '.[].text'
# yaml
pdsx -r zzstoatzz.io ls app.bsky.actor.profile -o yaml
# table
pdsx -r zzstoatzz.io ls app.bsky.feed.post -o table --limit 5
# compact (default)
pdsx -r zzstoatzz.io ls app.bsky.feed.post
examples
# read someone's bio
pdsx -r zzstoatzz.io ls app.bsky.actor.profile -o json | jq -r '.[0].description'
# get recent posts
pdsx -r did:plc:o53crari67ge7bvbv273lxln ls app.bsky.feed.post --limit 3 -o json
common collections
| collection | contains |
|---|
app.bsky.feed.post | posts/skeets |
app.bsky.actor.profile | user profile |
app.bsky.feed.like | likes |
app.bsky.graph.follow | follows |
app.bsky.feed.repost | reposts |
app.bsky.graph.list | lists |
what’s next