bluesky-style
simulates Bluesky AT Protocol com.atproto (2024-Q4)
verification
use it
# add to stunt.yaml
services:
bluesky:
adapter: embedded:bluesky-style
# then
$ stunt upThe embedded: source extracts this adapter from the binary — no git clone, fully offline.
how to mock the Bluesky AT Protocol API locally
Install stunt, paste the service block above into stunt.yaml, run stunt up — then point your client at localhost instead of Bluesky AT Protocol. It works offline, keeps state across requests and restarts, and every response is synthetic: the route shapes, status codes, pagination, and webhook delivery follow the real Bluesky AT Protocol com.atproto (2024-Q4) surface — the data is fake, the behavior is real.
backing stores
api surface (7)
generated from the adapter manifest — exactly what boots, nothing more · covers 3% of the real API's 202 routes (derived from spec atproto lexicons app.bsky.* + com.atproto.* (XRPC: query=GET, procedure=POST; records/objects/subscriptions skipped))
SDK-verified behaviors (8)
- ✓login rides createSession and adopts did/handle/tokens
- ✓agent.post creates an app.bsky.feed.post record
- ✓searchPosts finds the created post by its text
- ✓getProfile resolves the session actor with counts
- ✓resolveHandle is a public read (no session)
- ✓unauthenticated record writes surface as XRPC 401s
- ✓deletePost removes the record from search
- ✓refreshSession rotates the token pair via the SDK
Not implemented (7)
- No repo reads: com.atproto.repo getRecord, listRecords, describeRepo, uploadBlob
- No com.atproto.server getSession or deleteSession
- No app.bsky.feed getTimeline, getPostThread, getFeed, getLikes
- No app.bsky.graph getFollows, getFollowers, mutes, blocks
- No app.bsky.notification listNotifications or getUnreadCount
- No app.bsky.actor updateProfile or preference endpoints
- No com.atproto.moderation createReport; no app.bsky.chat conversations
Differs from the real API (4)
- searchPosts returns seeded synthetic results, not an index over created records
- createSession mints tokens for any identifier/password pair; no credential check
- refreshSession invalidates the old accessJwt too; real AT Protocol leaves it valid to exp
- cids cycle a fixed pool of 8 real CIDv1 strings rather than hashing record content