···11# hermes
2233-is a type-safe XRPC client for atproto.
33+is a set of libraries that work together to provide a type-safe XRPC client for atproto.
4455Hermes provides three components:
6677- **hermes** - Core library for making XRPC calls
88- **hermes-cli** - Code generator for atproto lexicons
99-- **hermes_ppx** - PPX extension for ergonomic API calls
99+- **hermes_ppx** (optional) - PPX extension for ergonomic API calls
10101111### table of contents
12121313- [Quick Start](#quick-start)
1414- [Complete Example](#complete-example)
1515-- [Installation](#installation)
1615- [hermes](#hermes-lib)
1716 - [Session Management](#session-management)
1817 - [Making XRPC Calls](#making-xrpc-calls)
···30293130## quick start
32313232+You'll need your lexicon `.json` files in a directory somewhere. Start by running `hermes-cli` to generate modules from your lexicons.
3333+3434+```bash
3535+hermes-cli generate ./lexicons/ --output=./hermes_lexicons
3636+```
3737+3838+You can find the full set of options for `hermes-cli` [here](#options).
3939+4040+A `hermes_lexicons` directory will be created with generated modules for each lexicon found in `./lexicons`. You can now use these modules in your code.
4141+3342```ocaml
3434-open Hermes_lexicons (* generate lexicons using hermes-cli! *)
4343+open Hermes_lexicons (* generated using hermes-cli *)
3544open Lwt.Syntax
36453746let () = Lwt_main.run begin
···47564857## complete example
49585959+You can add the `hermes_ppx` extension ([here's how!](#setup)) for more ergonomic API calls.
6060+5061```ocaml
5151-open Hermes_lexicons (* generate lexicons using hermes-cli! *)
6262+open Hermes_lexicons (* generated using hermes-cli *)
5263open Lwt.Syntax
53645465let main () =
5566 (* Set up credential manager with persistence *)
5656- let manager = Hermes.make_credential_manager ~service:"https://pegasus.example" () in
6767+ let manager = Hermes.make_credential_manager ~service:"https://pds.example" () in
57685869 Hermes.on_session_update manager (fun session ->
5970 let json = Hermes.session_to_yojson session in
···102113let () = Lwt_main.run (main ())
103114```
104115105105-## installation
106106-107107-Add to your `dune-project`:
108108-109109-```lisp
110110-(depends
111111- hermes
112112- hermes_ppx)
113113-```
114114-115116<h2 id="hermes-lib">hermes</h2>
116117117118### session management
···232233lib/generated/
233234├── dune
234235├── lexicons.ml # Re-exports all modules
235235-└── app/
236236- └── bsky/
237237- └── actor/
238238- └── getProfile.ml
236236+└── app_bsky_actor_getProfile.ml
239237```
240238241239Each endpoint module contains:
242240243241```ocaml
244244-module GetProfile = struct
242242+module Main = struct
245243 type params = {
246244 actor: string;
247245 } [@@deriving yojson]
···278276279277### bytes encoding
280278281281-Endpoints with non-JSON encoding are automatically detected and handled:
279279+Endpoints with non-JSON encoding are automatically detected and handled by `hermes-cli`:
282280283283-- **Queries with bytes output** (e.g., `com.atproto.sync.getBlob` with `encoding: "*/*"`):
284284- - Output type is `bytes * string` (data, content_type)
285285- - Generated code uses `Hermes.query_bytes`
286286-287287-- **Procedures with bytes input**:
288288- - Input is `?input:string` (optional raw bytes)
289289- - Generated code uses `Hermes.procedure_bytes`
281281+- Queries with bytes output (e.g., `com.atproto.sync.getBlob`): output is `bytes * string` (data, content_type)
282282+- Procedures with bytes input: input is `?input:bytes`
290283291284### union types
292285···301294302295<h2 id="hermes-ppx">hermes_ppx (PPX extension)</h2>
303296304304-Transforms `[%xrpc ...]` into generated module calls.
297297+transforms `[%xrpc ...]` into generated module calls.
305298306299### setup
307300