AT Protocol (atproto)

SkillSecurity

Guide for building on the AT Protocol (the "atmosphere") -- authoring Lexicons, building app views, consuming the firehose, working with identity (DIDs, handles), repositories, records, XRPC endpoints, and OAuth. Use this skill whenever the user is building anything on atproto/Bluesky/the atmosphere -- writing Lexicon JSON, calling com.atproto.* or app.bsky.* endpoints, parsing AT URIs (`at://...`), DIDs (`did:plc:...`, `did:web:...`), handles, TIDs, the indigo Go SDK (`github.com/bluesky-social/indigo`), the firehose / `subscribeRepos`, MSTs, CAR files, DAG-CBOR/DRISL, app views, feed generators, labelers, or PDS interactions. Triggers even if the user doesn't say "atproto" -- words like "lexicon", "PDS", "app view", "firehose", "did:plc", or `at://` URIs are enough.

Available today. Use it from your connected AI after setup.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Then ask your AI: use the AT Protocol (atproto) skill

What this skill tells your AI

The instructions your AI receives, as published by maragudk/fabrik in skills/atproto/SKILL.md and read by ahel’s review.

A guide for building on atproto -- the protocol behind Bluesky and the broader atmosphere of interoperable apps. This file is the overview and a router; deep details live in references/.

Mental model

atproto is a federated protocol where users own a signed, content-addressed data repository that any service can replicate. Apps are mostly app views -- services that consume the network firehose, validate records against a Lexicon schema, index them, and expose a read API. Writes go to the user's PDS via XRPC.

Five concepts to keep in your head:

  • DIDs identify accounts permanently (did:plc:... or did:web:...).
  • Handles are mutable, DNS-based usernames.
  • Repositories are signed, content-addressed Merkle Search Trees of records held on a PDS.
  • Lexicons are JSON schemas naming and validating records and HTTP endpoints, addressed by NSID (com.example.fooBar).
  • XRPC is HTTP transport for Lexicon-defined endpoints; the firehose is the WebSocket variant.

Service roles

Real systems are made of four roles. An app you build is usually #3.

  1. PDS (Personal Data Server) -- hosts a user's repo, signing keys, blobs. Authenticates clients. One per user.
  2. Relay -- subscribes to many PDSes' firehoses and aggregates into one stream. Optimisation, not source of truth.
  3. App View -- subscribes to a relay, validates records, indexes them, exposes XRPC reads. Bluesky's timeline service is one. A "feed generator" is a thin specialised app view.
  4. Labeler -- emits signed labels (moderation/badge metadata) on URIs. Has its own DID and signing key.

What to read next

This SKILL.md is intentionally thin. For anything beyond a high-level question, jump to the right reference:

You are doingRead
Authoring a Lexicon (records, queries, procedures, subscriptions)references/lexicon.md
Lexicon style guide -- naming, conventions, design patternsreferences/lexicon-style.md
Working with DIDs, handles, AT URIs, NSIDs, TIDs, record keysreferences/identity.md
Calling XRPC endpoints, handling errors, auth, proxyingreferences/xrpc.md
Reading repos, commits, MSTs, CAR files, the data modelreferences/repository.md
Consuming the firehose / subscribeRepos, event framingreferences/firehose.md
OAuth client implementation specificsreferences/oauth.md
Designing an app view end-to-end (the most common task)references/app-view.md
Picking a Go package from indigo, code sketchesreferences/indigo-go.md

If a question spans several topics, start with app-view.md -- it stitches the others together.

Default stack for Markus's Go projects

  • Identity, syntax, repo, lexicon, XRPC, OAuth: the indigo Go SDK (github.com/bluesky-social/indigo). See references/indigo-go.md.
  • Indexing storage: SQLite or Postgres. Persist the firehose cursor in the same database.
  • Serving HTML: gomponents + Datastar, per the existing fabrik skills.

The most common gotchas

These bite people the first time they build anything on atproto:

  • Handles are not durable. Always store DIDs as the primary identifier; cache handles separately and refresh on #identity events.
  • Lexicons can never tighten or loosen constraints after publication. Add optional fields only; mint a new NSID for breaking changes.
  • Floats are not in the data model. Use integers, or strings for fixed-point.
  • $type is required on records, blobs, and union variants. Strict clients silently drop records without it.
  • TID timestamps are advisory. Use your own indexedAt for ordering.
  • EXIF stripping on uploaded blobs is the client's job, not the PDS's.
  • Bidirectional verification is mandatory when resolving handles -- handle->DID, then DID->handle. Otherwise anyone can claim any handle.

Spec index

https://atproto.com/specs/atp -- starting point for everything below.

SpecURL
Lexiconhttps://atproto.com/specs/lexicon
Data modelhttps://atproto.com/specs/data-model
Repositoryhttps://atproto.com/specs/repository
XRPChttps://atproto.com/specs/xrpc
Sync / firehosehttps://atproto.com/specs/sync
Event stream framinghttps://atproto.com/specs/event-stream
OAuthhttps://atproto.com/specs/oauth
DIDshttps://atproto.com/specs/did
Handleshttps://atproto.com/specs/handle
NSIDshttps://atproto.com/specs/nsid
TIDshttps://atproto.com/specs/tid
Record keyshttps://atproto.com/specs/record-key
AT URIhttps://atproto.com/specs/at-uri-scheme
Blobshttps://atproto.com/specs/blob
Labelshttps://atproto.com/specs/label
Cryptographyhttps://atproto.com/specs/cryptography
Permissionshttps://atproto.com/specs/permission
Accountshttps://atproto.com/specs/account

Worked examples: Statusphere tutorial (TS), indigo services (Go), Bluesky's canonical Lexicons (the best style reference).

Signals

GitHub stars
28
Forks
2
Last commit
Sep 2026
Advanced
Item type
skill
Key
atproto
Source
github.com/maragudk/fabrik