a collection of lightweight TypeScript packages for AT Protocol, the protocol powering Bluesky
atproto
bluesky
typescript
npm
1atcute is a monorepository, a collection of lightweight and high-quality TypeScript libraries for AT
2Protocol (the protocol powering Bluesky.)
3
4the packages are organized into categories under `packages/`:
5
6- `clients/`: API client implementations
7- `servers/`: XRPC server framework and runtime adapters
8- `oauth/`: OAuth implementations
9- `lexicons/`: lexicon schema tooling
10- `definitions/`: generated validation and type definitions for various AT Protocol services
11- `identity/`: DID document and handle resolutions, and did:plc validation
12- `utilities/`: DASL codecs, data encoding and atproto primitives
13- `misc/`: general-purpose utilities
14- `bluesky/`: Bluesky-specific helpers
15- `internal/`: non-public development packages
16
17## development notes
18
19### project management
20
21- tools like Node.js, Bun and pnpm are managed by mise
22- Node.js can run TypeScript files directly (`node index.ts`, strip types is unflagged)
23- check `pnpm view <package>` before adding a new dependency
24
25#### root-level tasks
26
27- format via `pnpm run fmt` (oxfmt)
28- lint via `pnpm run lint` (oxlint)
29
30#### package-level tasks
31
32run these inside the package directory, e.g. `cd packages/utilities/cbor; pnpm run ...`
33
34- build via `pnpm run build` (tsgo, includes typechecking)
35- test via `pnpm run test` (vitest)
36
37### code writing
38
39- new files should be in kebab-case
40- use tabs for indentation, spaces allowed for diagrams in comments
41- use single quotes for strings; use template literals for localization strings (user-facing
42 strings, error messages)
43- add trailing commas
44- prefer arrow functions, but use regular methods in classes unless arrow functions are necessary
45 (e.g., when passing the method as a callback that needs `this` binding)
46- use braces for control statements, even single-line bodies
47- use bare blocks `{ }` to group related code and limit variable scope
48- prefer `switch` over `if`/`else if` chains when branching on a single discriminant value
49- avoid barrel exports (index files that re-export from other modules); import directly from source
50- use `// #region <name>` and `// #endregion` to denote regions when a file needs to contain a lot
51 of code
52- a parameter should be optional only when callers genuinely split between passing a value and
53 relying on the default; if every caller passes a value, make it required; if no caller would ever
54 change it, it should not be a parameter at all
55- avoid optional parameters that change behavioral modes or make the function do different things
56 based on presence/absence; prefer a separate function with a clearer name instead
57- avoid type assertions (`as Type`, `as const`) unless TypeScript actually errors without them; when
58 it does error, prefer finding a solution that satisfies the type system naturally before resorting
59 to an assertion
60
61### commit workflow
62
63we use conventional commits with these rules:
64
65- accepted types: `feat`, `fix`, `refactor`, `docs`, `chore`
66 - `docs`: only applies to Markdown documents (README and similar)
67 - `chore`: only applies to build/tooling/dependency changes, and mass-autofixes from linters and
68 formatters
69- optional scope is the package name, e.g. `refactor(package-a):`
70- omit the scope when the change does not involve any specific package, or when it touches most/all
71 packages
72- never list multiple packages in the scope (e.g. `refactor(package-a,package-b)` is forbidden)
73- append `!` after the type/scope to mark breaking changes, e.g. `feat(package-a)!:` or `refactor!:`
74
75scope selection when multiple packages are involved:
76
77- if the change primarily involves `package-a` over `package-b`, pick `package-a`
78- if changes in `package-a` and `package-b` hinge on `package-c` (even if `package-c` itself was not
79 modified), pick `package-c`
80
81granularity — each commit should represent one logical change:
82
83- split distinct changes into separate commits rather than bundling them
84- pair each changeset with the single commit it describes, so the changeset's git hash maps to the
85 right change; do not write one changeset covering multiple commits
86- pair each README update with the commit it documents, rather than batching doc updates across
87 multiple changes
88
89### documentation
90
91- documentations include README, code comments, commit messages
92- any writing should be in lowercase, except for proper nouns, acronyms and 'I'; this does not apply
93 to public-facing interfaces like web UI
94- only comment non-trivial code, focusing on _why_ rather than _what_
95- write comments and JSDoc in lowercase (except proper nouns, acronyms, and 'I')
96- add JSDoc comments to new publicly exported functions, methods, classes, fields, and enums
97- JSDoc should include proper annotations:
98 - use `@param` for parameters (no dashes after param names)
99 - use `@returns` for return values
100 - use `@throws` for exceptions when applicable
101 - keep descriptions concise but informative
102
103### agentic coding
104
105- `.research/` directory in the project root serves as a workspace for temporary experiments,
106 analysis, and planning materials. create if not present (it's gitignored). this directory may
107 contain cloned repositories or other reference materials that can help inform implementation
108 decisions
109- this document is intentionally incomplete; discover everything else in the repo
110- don't make assumptions or speculate about code, plans, or requirements without exploring first;
111 pause and ask for clarification when you're still unsure after looking into it
112- in plan mode, present the plan for review before exiting to allow for feedback or follow-up
113 questions
114- when debugging problems, isolate the root cause first before attempting fixes: add logging,
115 reproduce the issue, narrow down the scope, and confirm the exact source of the problem
116
117### Claude Code-specific
118
119- Explore subagent may not be accurate; verify findings as needed
120- never spawn subagents to read and return file contents; read files directly in the main context.
121 subagents should perform searches or answer specific questions, not act as file I/O proxies
122- don't use WebFetch to retrieve full page contents; it answers a question about a URL, not dumps
123 the raw content. use `curl` if you need the complete unsummarized response
124
125### external repository research
126
127use `@oomfware/cgr` to ask questions about external repositories:
128
129```
130npx @oomfware/cgr ask [options] <repo>[#branch] <question>
131
132options:
133 -m, --model <model> model to use: opus, sonnet, haiku (default: haiku)
134 -d, --deep clone full history (enables git log/blame/show)
135 -w, --with <repo> additional repository to include, supports #branch (repeatable)
136```
137
138useful repositories for development:
139
140- `github.com/bluesky-social/atproto` for AT Protocol reference implementation, lexicons, XRPC
141- `github.com/bluesky-social/social-app` for Bluesky app patterns, API usage examples
142- `github.com/bluesky-social/feed-generator` for feed generator architecture
143- `github.com/bluesky-social/indigo` for Go implementation, alternative design approaches
144- `github.com/bluesky-social/ozone` for moderation service patterns
145- `github.com/bluesky-social/proposals` for AT Protocol proposals and specifications
146- `github.com/bluesky-social/atproto-website` for AT Protocol spec documentation
147- `github.com/DavidBuchanan314/atmst` for MST implementation in Python (@atcute/mst is derived from
148 this)
149- `github.com/DavidBuchanan314/millipds` for practical atmst usage patterns (Python)
150- `github.com/darobin/dasl.ing` for DASL specification
151- `github.com/did-method-plc/did-method-plc` for DID PLC implementation reference
152
153broad questions work for getting oriented; detailed questions get precise answers. include
154file/folder paths when you know them, and reference details from previous answers in follow-ups.
155
156run `npx @oomfware/cgr --help` for more options.