···66pub use smol_str;
77pub use url;
8899-/// A copy-on-write immutable string type that uses [`SmolStr`] for
99+/// A copy-on-write immutable string type that uses [`smol_str::SmolStr`] for
1010/// the "owned" variant.
1111#[macro_use]
1212pub mod cowstr;
-2
crates/jacquard-common/src/types/crypto.rs
···22222323/// Known multicodec key codecs for Multikey public keys
2424///
2525-2626-/// ```
2725#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2826pub enum KeyCodec {
2927 /// Ed25519
+2-2
crates/jacquard-common/src/types/did_doc.rs
···3535 #[serde(borrow)]
3636 pub id: Did<'a>,
37373838- /// Alternate identifiers for the subject, such as at://<handle>
3838+ /// Alternate identifiers for the subject, such as at://\<handle\>
3939 #[serde(borrow)]
4040 pub also_known_as: Option<Vec<CowStr<'a>>>,
4141···6666}
67676868impl<'a> DidDocument<'a> {
6969- /// Extract validated handles from `alsoKnownAs` entries like `at://<handle>`.
6969+ /// Extract validated handles from `alsoKnownAs` entries like `at://\<handle\>`.
7070 pub fn handles(&self) -> Vec<Handle<'static>> {
7171 self.also_known_as
7272 .as_ref()
+2-2
crates/jacquard/src/identity/resolver.rs
···161161/// Handle → DID fallback step.
162162#[derive(Debug, Clone, Copy, PartialEq, Eq)]
163163pub enum HandleStep {
164164- /// DNS TXT _atproto.<handle>
164164+ /// DNS TXT _atproto.\<handle\>
165165 DnsTxt,
166166- /// HTTPS GET https://<handle>/.well-known/atproto-did
166166+ /// HTTPS GET https://\<handle\>/.well-known/atproto-did
167167 HttpsWellKnown,
168168 /// XRPC com.atproto.identity.resolveHandle against a provided PDS base
169169 PdsResolveHandle,
+14-23
crates/jacquard/src/lib.rs
···4646//! #[tokio::main]
4747//! async fn main() -> miette::Result<()> {
4848//! let args = Args::parse();
4949-//!
5049//! // Create HTTP client
5150//! let url = url::Url::parse(&args.pds).unwrap();
5251//! let client = BasicClient::new(url);
5353-//!
5452//! // Create session
5553//! let session = Session::from(
5654//! client
···6361//! .await?
6462//! .into_output()?,
6563//! );
6666-//!
6767-//! println!("logged in as {} ({})", session.handle, session.did);
6864//! client.set_session(session).await.unwrap();
6969-//!
7065//! // Fetch timeline
7166//! println!("\nfetching timeline...");
7267//! let timeline = client
7368//! .send(GetTimeline::new().limit(5).build())
7469//! .await?
7570//! .into_output()?;
7676-//!
7771//! println!("\ntimeline ({} posts):", timeline.feed.len());
7872//! for (i, post) in timeline.feed.iter().enumerate() {
7973//! println!("\n{}. by {}", i + 1, post.post.author.handle);
···8276//! serde_json::to_string_pretty(&post.post.record).into_diagnostic()?
8377//! );
8478//! }
8585-//!
8679//! Ok(())
8780//! }
8881//! ```
8982//!
9090-//! ## Clients
8383+//! ## Client options:
9184//!
9285//! - Stateless XRPC: any `HttpClient` (e.g., `reqwest::Client`) implements `XrpcExt`,
9386//! which provides `xrpc(base: Url) -> XrpcCall` for per-request calls with
9487//! optional `CallOptions` (auth, proxy, labelers, headers). Useful when you
9588//! want to pass auth on each call or build advanced flows.
9696-//! Example
9797-//! ```ignore
9898-//! use jacquard::client::XrpcExt;
9999-//! use jacquard::api::app_bsky::feed::get_author_feed::GetAuthorFeed;
100100-//! use jacquard::types::ident::AtIdentifier;
101101-//!
8989+//! ```no_run
9090+//! # use jacquard::client::XrpcExt;
9191+//! # use jacquard::api::app_bsky::feed::get_author_feed::GetAuthorFeed;
9292+//! # use jacquard::types::ident::AtIdentifier;
9393+//! #
10294//! #[tokio::main]
10395//! async fn main() -> anyhow::Result<()> {
10496//! let http = reqwest::Client::new();
···124116//! `AtClient<reqwest::Client, MemoryTokenStore>` with a `new(Url)` constructor.
125117//!
126118//! Per-request overrides (stateless)
127127-//! ```ignore
128128-//! use jacquard::client::{XrpcExt, AuthorizationToken};
129129-//! use jacquard::api::app_bsky::feed::get_author_feed::GetAuthorFeed;
130130-//! use jacquard::types::ident::AtIdentifier;
131131-//! use jacquard::CowStr;
132132-//! use miette::IntoDiagnostic;
133133-//!
119119+//! ```no_run
120120+//! # use jacquard::client::{XrpcExt, AuthorizationToken};
121121+//! # use jacquard::api::app_bsky::feed::get_author_feed::GetAuthorFeed;
122122+//! # use jacquard::types::ident::AtIdentifier;
123123+//! # use jacquard::CowStr;
124124+//! # use miette::IntoDiagnostic;
125125+//! #
134126//! #[tokio::main]
135127//! async fn main() -> miette::Result<()> {
136128//! let http = reqwest::Client::new();
···157149//! - Use `MemoryTokenStore` for ephemeral sessions, tests, and CLIs.
158150//! - For persistence, `FileTokenStore` stores session tokens as JSON on disk.
159151//! See `client::token::FileTokenStore` docs for details.
160160-//! Example
161161-//! ```ignore
152152+//! ```no_run
162153//! use jacquard::client::{AtClient, FileTokenStore};
163154//! let base = url::Url::parse("https://bsky.social").unwrap();
164155//! let store = FileTokenStore::new("/tmp/jacquard-session.json");