AT Protocol API (@atproto/api)

The official TypeScript client for AT Protocol and Bluesky, with session management, OAuth, moderation, and RichText handling built in.

SDK
npm
v0.20.42
9,624stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
91/100Excellent
Development Activity96
Maintenance100
Community72
Maturity56
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
82/100Excellent
Architecture84
Code Quality85
Innovation78
Learning Curve80

@atproto/api is the reference client library for AT Protocol, the decentralized social networking protocol behind Bluesky. It ships an Agent class that wraps session management (both legacy app-password login and OAuth-based sessions from the @atproto/oauth-client-* family) around a fully typed, code-generated RPC client covering the com.atproto, app.bsky, chat.bsky, and tools.ozone Lexicon namespaces.

Beyond raw API calls, the package bundles the domain logic that Bluesky’s own clients rely on: a moderation engine that evaluates labels, mutewords, and blocklists per content subject (posts, profiles, feed generators, notifications, user lists) and returns render-ready UI decisions, plus a RichText library that solves the gnarly problem of converting between JavaScript’s UTF-16 strings and the protocol’s UTF-8/grapheme-based facet offsets for mentions and links.

Because the RPC surface is generated directly from the protocol’s Lexicon JSON schema definitions rather than hand-written, the client stays in lockstep with the evolving protocol while still exposing convenience methods (agent.getTimeline(), agent.post(), agent.follow(), etc.) for the most common operations, alongside raw namespace access (agent.com.atproto.repo.createRecord()) for anything the convenience layer doesn’t cover yet.

What You Get

  • An Agent class unifying session management, RPC calls, and convenience wrappers for feeds, posts, follows, likes, and profiles
  • OAuth-based session support alongside the legacy app-password CredentialSession flow
  • A code-generated, fully typed client for every com.atproto, app.bsky, chat.bsky, and tools.ozone Lexicon method and record type
  • A moderation engine (moderatePost, moderateProfile, and subject-specific variants) that turns labels, mutewords, and blocklists into concrete UI render decisions
  • A RichText library that detects mentions/links and correctly converts between UTF-16 string offsets and the protocol’s UTF-8 grapheme-based facets
  • Direct namespace access to raw XRPC methods (agent.com.atproto.*, agent.app.bsky.*) for anything not covered by the convenience API

Common Use Cases

  • Building a third-party Bluesky client or browser extension that reads and posts to feeds
  • Implementing OAuth login and session persistence for an AT Protocol app via @atproto/oauth-client-browser or -node
  • Rendering user-generated posts with correct moderation behavior (blurring, filtering, content warnings) based on a viewer’s preferences and labelers
  • Composing and parsing rich text posts with accurate mention/link facets and grapheme-aware character counting
  • Interacting directly with an AT Protocol PDS or the Bluesky App View through typed, Lexicon-generated RPC calls for automation or bot accounts

Under The Hood

Architecture The package centers on an Agent class (in src/agent.ts) that composes a SessionManager with a generated XRPC client, exposing convenience methods for feeds, posts, follows, and profiles while also attaching namespaced access (ComNS, AppNS, ChatNS, ToolsNS) generated from Lexicon schemas via the internal lex-cli codegen tool into src/client/ (gitignored, rebuilt from the repo’s /lexicons JSON definitions on every build). Two legacy subclasses, AtpAgent and BskyAgent, sit alongside Agent for backward compatibility with older session-management styles. Domain logic is cleanly separated from the RPC layer: src/moderation/ holds per-subject decision functions (post, profile, account, notification, feed-generator, user-list, status) that consume label/preference data and emit a ui()-queryable moderation-state object, and src/rich-text/ handles UTF-16/UTF-8 conversion, grapheme segmentation, and facet detection independently of any network code. Because nearly every export in index.ts composes through the Agent/session layer or the generated client, a change to either would ripple across the whole public surface.

Tech Stack Written in TypeScript targeting Node >=22, published as a pure ESM package ("type": "module"). It depends on sibling workspace packages (@atproto/common-web, @atproto/lexicon, @atproto/syntax, @atproto/xrpc) resolved via pnpm’s workspace:^ protocol inside a pnpm monorepo, plus zod for schema validation, multiformats for CID/multibase handling, await-lock for session-mutation concurrency, and tlds for domain validation in mention/link detection. The RPC client itself isn’t hand-written — it’s generated from Lexicon JSON schema files at the repo root via the project’s own lex-cli tool. Builds run through tsc project references (tsconfig.build.json); tests run under Jest with --experimental-vm-modules for ESM support; linting and formatting are centralized at the monorepo root via ESLint and Prettier configs, with CI including an automated Claude-based PR review workflow and changeset-driven npm publishing.

Code Quality The package carries 14+ dedicated test files covering moderation behavior across multiple label/mutewords/quote-post scenarios, rich-text detection and sanitization, agent/session flows, request dispatching, and error handling, using custom Jest matchers (toBeModerationResult) for readable assertions on complex moderation output. Types are pervasive and largely generated rather than hand-maintained, reducing drift between the wire protocol and the TypeScript surface, and zod is used for runtime validation of user-controlled values like muted words. No obvious gaps in error handling were found in the core agent and moderation modules, and the monorepo enforces linting and an automated review bot on every PR.

What Makes It Unique Most API client libraries are either hand-written wrappers or fully generic OpenAPI-generated stubs; this one is generated from a first-class schema language (Lexicon) purpose-built for a decentralized protocol, which keeps the client honest against protocol changes across many independent packages in the same monorepo. On top of that generated core, it layers two genuinely hard, domain-specific problems most SDKs never touch: a client-side moderation decision engine that mirrors what Bluesky’s own apps use to decide what to blur, filter, or warn on, and a RichText utility that correctly bridges JavaScript’s UTF-16 string model with the protocol’s UTF-8/grapheme-based text facets — a subtle correctness problem (emoji and multi-codepoint graphemes in particular) that’s easy to get wrong and rarely solved this thoroughly in a general-purpose client.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search