Skip to main content
A resolver is an out-of-process program that Hibi calls to grade an anchor or run a verifier. Hibi talks to it in JSONL-RPC over stdio, one JSON message per line. The SDKs exist so you don’t have to hand-roll that framing or re-derive the message shapes: they give you typed scaffolding in TypeScript or Rust, and you fill in the drift logic. For the protocol itself (the methods, the request/response shapes, the default-deny manifest), start at Resolvers. The SDKs are the language bindings on top of it.

TypeScript SDK

Write resolvers in TypeScript, run them with Bun.

Rust SDK

A native crate with a worked echo_resolver example.

What both SDKs implement

Every resolver, whatever language it’s written in, answers the same three-method protocol. Each SDK reads framed requests from stdin, dispatches to your handler, and writes framed responses to stdout. On resolve, the engine reads the relevant files itself and passes them to you as files { doc, code: { path: content } }; your resolver never reaches into the working tree. The verdict you return reads like the rest of Hibi’s output: doc:unchanged · code:changed · behavior:at-risk (see Verdicts for the full vocabulary). Verifier kinds are open strings, not a schema enum: the engine routes a verify call to your resolver by exact string match, so a verifier reaches you only when its kind appears in the verifierKinds you returned from describe. Declare "command", "snapshot", or any string you invent — the verify request and response contract is the same for every kind; only the routing key varies.
A resolver that grades anchors is advisory unless it’s the engine’s own built-in drift logic. An opt-in semantic advisor may explain or triage a verdict; it never gates and never marks a claim supported. The line stays at Resolvers.

The shared contract

The two SDKs are not independent re-implementations that can drift apart. Both bind to one source of truth: every message type has a JSON Schema in schemas/, generated from Hibi’s single Zod model (src/core/model.ts) and the protocol definition (src/resolver/protocol.ts). That single generation step has two payoffs:
  • The TypeScript and Rust bindings stay in lockstep with the engine: when the model changes, the schemas regenerate and both SDKs follow.
  • A resolver in any language with a JSON Schema toolchain can validate its messages against the same canonical contract, even without an SDK. The SDKs are a convenience, not a requirement.
You can emit the schemas yourself from the CLI:

Building the Rust SDK

The Rust SDK is a standalone crate: it builds without the CLI, so you can develop a native resolver in isolation and run the worked example:

Next

Resolvers

The protocol the SDKs implement: methods, the JSONL-RPC seam, the default-deny manifest.

Behavioral claims

Where verify fits: executable verifiers, the change-gate, and the no-model boundary.