A better Rust ATProto crate
103
fork

Configure Feed

Select the types of activity you want to include in your feed.

1# CLAUDE.md 2 3This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. 4 5## Project Overview 6 7Jacquard is a suite of Rust crates for the AT Protocol (atproto/Bluesky). The project emphasizes spec-compliant, validated, performant baseline types with minimal boilerplate. Key design goals: 8 9- Validated AT Protocol types including typed at:// URIs 10- Custom lexicon extension support 11- Lexicon `Value` type for working with unknown atproto data (dag-cbor or json) 12- Using as much or as little of the crates as needed 13 14## Workspace Structure 15 16This is a Cargo workspace with several crates: 17 18- **jacquard**: Main library crate with XRPC client and public API surface (re-exports jacquard-api and jacquard-common) 19- **jacquard-common**: Core AT Protocol types (DIDs, handles, at-URIs, NSIDs, TIDs, CIDs, etc.) and the `CowStr` type for efficient string handling 20- **jacquard-lexicon**: Lexicon parsing and Rust code generation from lexicon schemas 21- **jacquard-api**: Generated API bindings from lexicon schemas (implementation detail, not directly used by consumers) 22- **jacquard-derive**: Attribute macros (`#[lexicon]`, `#[open_union]`) for lexicon structures 23 24## Development Commands 25 26### Using Nix (preferred) 27```bash 28# Enter dev shell 29nix develop 30 31# Build 32nix build 33 34# Run 35nix develop -c cargo run 36``` 37 38### Using Cargo/Just 39```bash 40# Build 41cargo build 42 43# Run tests 44cargo test 45 46# Run specific test 47cargo test <test_name> 48 49# Run specific package tests 50cargo test -p <package_name> 51 52# Run 53cargo run 54 55# Auto-recompile and run 56just watch [ARGS] 57 58# Format and lint all 59just pre-commit-all 60 61# Generate API bindings from lexicon schemas 62cargo run -p jacquard-lexicon --bin jacquard-codegen -- -i <input_dir> -o <output_dir> [-r <root_module>] 63# Example: 64cargo run -p jacquard-lexicon --bin jacquard-codegen -- -i crates/jacquard-lexicon/tests/fixtures/lexicons/atproto/lexicons -o crates/jacquard-api/src -r crate 65``` 66 67## String Type Pattern 68 69The codebase uses a consistent pattern for validated string types. Each type should have: 70 71### Constructors 72- `new()`: Construct from a string slice with appropriate lifetime (borrows) 73- `new_owned()`: Construct from `impl AsRef<str>`, taking ownership 74- `new_static()`: Construct from `&'static str` using `SmolStr`/`CowStr`'s static constructor (no allocation) 75- `raw()`: Same as `new()` but panics instead of returning `Result` 76- `unchecked()`: Same as `new()` but doesn't validate (marked `unsafe`) 77- `as_str()`: Return string slice 78 79### Traits 80All string types should implement: 81- `Serialize` + `Deserialize` (custom impl for latter, sometimes for former) 82- `FromStr`, `Display` 83- `Debug`, `PartialEq`, `Eq`, `Hash`, `Clone` 84- `From<T> for String`, `CowStr`, `SmolStr` 85- `From<String>`, `From<CowStr>`, `From<SmolStr>`, or `TryFrom` if likely to fail 86- `AsRef<str>` 87- `Deref` with `Target = str` (usually) 88 89### Implementation Details 90- Use `#[repr(transparent)]` when possible (exception: at-uri type and components) 91- Use `SmolStr` directly as inner type if most instances will be under 24 bytes 92- Use `CowStr` for longer strings to allow borrowing from input 93- Implement `IntoStatic` trait to take ownership of string types 94 95## Code Style 96 97- Avoid comments for self-documenting code 98- Comments should not detail fixes when refactoring 99- Professional writing within source code and comments only 100- Prioritize long-term maintainability over implementation speed 101 102## Testing 103 104- Write test cases for all critical code 105- Tests can be run per-package or workspace-wide 106- Use `cargo test <name>` to run specific tests 107- Current test coverage: 89 tests in jacquard-common 108 109## Lexicon Code Generation 110 111The `jacquard-codegen` binary generates Rust types from AT Protocol Lexicon schemas: 112 113- Generates structs with `#[lexicon]` attribute for forward compatibility (captures unknown fields in `extra_data`) 114- Generates enums with `#[open_union]` attribute for handling unknown variants (unless marked `closed` in lexicon) 115- Resolves local refs (e.g., `#image` becomes `Image<'a>`) 116- Extracts doc comments from lexicon `description` fields 117- Adds header comments with `@generated` marker and lexicon NSID 118- Handles XRPC queries, procedures, subscriptions, and errors 119- Generates proper module tree with Rust 2018 style 120- **XrpcRequest trait**: Implemented directly on params/input structs (not marker types), with GATs for Output<'de> and Err<'de> 121- **IntoStatic trait**: All generated types implement `IntoStatic` to convert borrowed types to owned ('static) variants 122- **Collection trait**: Implemented on record types directly, with const NSID 123 124## Current State & Next Steps 125 126### Completed 127- ✅ Comprehensive validation tests for all core string types (handle, DID, NSID, TID, record key, AT-URI, datetime, language, identifier) 128- ✅ Validated implementations against AT Protocol specs and TypeScript reference implementation 129- ✅ String type interface standardization (Language now has `new_static()`, Datetime has full conversion traits) 130- ✅ Data serialization: Full serialize/deserialize for `Data<'_>`, `Array`, `Object` with format-specific handling (JSON vs CBOR) 131- ✅ CidLink wrapper type with automatic `{"$link": "cid"}` serialization in JSON 132- ✅ Integration test with real Bluesky thread data validates round-trip correctness 133- ✅ Lexicon code generation with forward compatibility and proper lifetime handling 134- ✅ IntoStatic implementations for all generated types (structs, enums, unions) 135- ✅ XrpcRequest trait with GATs, implemented on params/input types directly 136- ✅ HttpClient and XrpcClient traits with generic send_xrpc implementation 137- ✅ Response wrapper with parse() (borrowed) and into_output() (owned) methods 138- ✅ Structured error types (ClientError, TransportError, EncodeError, DecodeError, HttpError, AuthError) 139 140### Next Steps 1411. **Concrete HttpClient Implementation**: Implement HttpClient for reqwest::Client and potentially other HTTP clients 1422. **Error Handling Improvements**: Add XRPC error parsing, better HTTP status code handling, structured error responses 1433. **Authentication**: Session management, token refresh, DPoP support 1444. **Body Encoding**: Support for non-JSON encodings (CBOR, multipart, etc.) in procedures 1455. **Lexicon Resolution**: Fetch lexicons from web sources (atproto authorities, git repositories) and parse into corpus 1466. **Custom Lexicon Support**: Allow users to plug in their own generated lexicons alongside jacquard-api types in the client/server layer 1477. **Public API**: Design the main API surface in `jacquard` that re-exports and wraps generated types 1488. **DID Document Support**: Parsing, validation, and resolution of DID documents 1499. **OAuth Implementation**: OAuth flow support for authentication 15010. **Examples & Documentation**: Create examples and improve documentation 15111. **Testing**: Comprehensive tests for generated code and round-trip serialization