CLI tool
typst/hayagriva avatar
typst/hayagriva

Hayagriva: bibliography formatting for Rust apps that read YAML or BibTeX

Rusty bibliography management.

716 stars106 forksRustApache-2.0

At a glance

What is it?
Hayagriva is a Rust library and command line tool that stores literature in YAML, parses BibTeX and BibLaTeX, and formats citations and reference lists with Citation Style Language styles. It is aimed at people who want a bibliography engine inside a tool rather than a LaTeX macro package.
Who is it for?
Adopt Hayagriva if you are building a document tool or editor in Rust and need citations computed at runtime from YAML or Bib(La)TeX input, with the CSL style ecosystem available offline. Do not adopt it if your pipeline already ends in a TeX compile, because a biblatex based workflow formats the bibliography inside the typesetting run instead.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 17 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A bibliography engine that runs inside your program, not inside your typesetter

Most people who want formatted citations reach for a LaTeX package or a desktop reference manager. Hayagriva takes a different position: it is a Rust library that does the work itself, and it ships a command line front end as well. The project description is blunt about the category, "Rusty bibliography management", and the crate description in the package manifest is longer: "Work with references: Literature database management, storage, and citation formatting".

The intended users are programmers building tools that handle documents: an editor with a bibliography panel, a report generator, a script that turns a folder of notes into a formatted reference list. The project lists what it offers as data structures for literature collections, reading and writing those collections from YAML files, formatting entries into reference list entries and in-text citations as defined by popular style guides, interoperability with BibTeX, and querying items by type and available metadata.

Two design choices follow from that audience. First, storage is YAML rather than a database, so a collection is a file you can commit next to a document. Second, the formatting engine is Citation Style Language, the same style repository used by many other tools, so an author who already knows CSL styles gets the expected output without learning a private format.

The driver pipeline: CitationRequest in, formatted citations out

The API is built around a driver that you feed one request at a time and then close out. A `CitationRequest` is constructed from a list of `CitationItem` values together with a style and a set of locale files, and the driver returns formatted citations. When the run is finished, a `BibliographyRequest` produces the reference list. The README states plainly that to format entries you need to wrap them in a `CitationRequest`, and that each of these can reference multiple entries in their respective `CitationItem`s.

The style and the locales are objects you load yourself. A CSL style file is parsed with `IndependentStyle::from_xml`, and a locale is parsed with `LocaleFile::from_xml`, both coming from the `hayagriva::citationberg` module. The driver is then driven and finished like this:

rust
use hayagriva::io::from_yaml_str;

let bib = from_yaml_str(yaml).unwrap();
assert_eq!(bib.get("crazy-rich").unwrap().date().unwrap().year, 2014);

use hayagriva::{
    BibliographyDriver, BibliographyRequest, BufWriteFormat,
    CitationItem, CitationRequest,
};

let mut driver = BibliographyDriver::new();

for entry in bib.iter() {
    let items = vec![CitationItem::with_entry(entry)];
    driver.citation(CitationRequest::from_items(items, &style, &locales));
}

The important detail for an integrator is that `BibliographyDriver` is stateful across the run. Citations are submitted one at a time so that the driver can disambiguate clusters and order the bibliography, and only the `finish` call produces the final list. A caller who wants one bibliography per document should create a new driver for that document, because a single driver accumulates everything it is given.

Style coverage comes from the CSL repository, and only a subset is bundled

Hayagriva implements Citation Style Language, and it states that it supports all styles provided in the official Citation Style Language repository, currently over 2,600. That number is a property of the upstream style collection, not of what ships in the crate.

What ships locally is smaller. The README says you can supply your own CSL files or choose from about 100 bundled citation styles using the `archive` feature. That feature is a plain Cargo feature, and the manifest makes the cost visible:

toml
[features]
default = ["biblatex", "archive"]
cli = ["clap", "strum"]
archive = ["ciborium"]
csl-json = ["citationberg/json"]

The `archive` feature pulls in `ciborium`, a compact binary serialization crate, which is how the bundled styles are stored. `csl-json` is separate and enables JSON style support in the citationberg dependency. The manifest also declares a `citeproc` test whose `required-features` are `csl-json`, so the JSON style path is exercised only when that feature is enabled. Applications that want offline coverage of common styles can rely on the default feature set; applications that need a specific style that is not bundled can point the loader at an XML file themselves.

Selectors filter by media type and by the parent relation

Beyond formatting, Hayagriva has a query language of its own for slicing a collection. The README calls it a custom selector language and points to the `docs/selectors.md` file in the repository for the details. Selectors match on type of media, and they can also express relationships between an item and its parent, so a query can distinguish a journal article from a book chapter by looking at what the entry hangs from.

A selector can be written inline with the `select!` macro, which the README recommends over runtime parsing because it avoids the cost of parsing a constant selector:

rust
use hayagriva::select;
use hayagriva::io::from_yaml_str;

let entries = from_yaml_str(yaml).unwrap();
let journal = select!((Article["date"]) > ("journal":Periodical));
assert!(journal.matches(entries.nth(0).unwrap()));

Two functions answer slightly different questions. `Selector::matches` tells you only whether an entry matches. `Selector::apply` goes further and lets you keep working with data taken from the parents of a matching entry. The README warns about the difference: `apply` returns `Some` even when no sub-entry was bound, or when the hash map is empty. That is a real footgun in code that assumes an empty result means no match, and it is worth handling explicitly rather than relying on the `Option` alone.

Installing the CLI and pointing it at a literature file

The CLI is a Cargo feature rather than a separate binary package. The manifest declares it as a `[[bin]]` target named `hayagriva` whose `required-features` are `cli`, and the `cli` feature turns on `clap` and `strum`. Installing it is a single command:

bash
cargo install hayagriva --features cli

Cargo will install the Hayagriva Command Line Interface, and after that you need a data file. The YAML format is the native one, and the project points to a dedicated `docs/file-format.md` for how to write one. A minimal entry looks like this, with the type, title, author list, date and a serial number holding a DOI:

yaml
dependence:
    type: Article
    title: The program dependence graph and its use in optimization
    author: ["Ferrante, Jeanne", "Ottenstein, Karl J.", "Warren, Joe D."]
    date: 1987-07
    serial-number:
        doi: "10.1145/24039.24041"
    parent:
        type: Periodical
        title: ACM Transactions on Programming Languages and Systems
        volume:

The `parent` block is what lets a style print the journal name and volume above the article title. The README does not document the individual CLI subcommands or their flags, so the exact command line for rendering a specific style is not described there; that part of the surface has to be read from the built binary or the generated help output. BibTeX and BibLaTeX files are also accepted as input, since those are handled by the default `biblatex` feature.

Turning off default features removes BibLaTeX handling, and the README's own version example is stale

If a project does not need Bib(La)TeX compatibility, the README shows how to depend on Hayagriva without the default features:

toml
[dependencies]
hayagriva = { version = "0.9", default-features = false }

Two things are worth noticing. First, disabling defaults drops `biblatex` and `archive`, so `io::from_biblatex_str` and the roughly 100 bundled styles are gone with them. The core library, the YAML path, the CSL loader and the selectors remain. Second, the version in that snippet is 0.9, while the crate manifest in the repository declares version 0.10.1, and the published releases include v0.10.0 on 2026-06-05 and v0.10.1 on 2026-06-14, after v0.9.1 on 2025-09-26. Anyone copying the snippet verbatim into a new Cargo.toml would pin to the older series.

There is also a route for callers who already hold a `biblatex` crate entry and want the native `Entry` type instead of a conversion step:

rust
use hayagriva::Entry;
let converted: Entry = your_biblatex_entry.into();

For that path you have to depend on the `biblatex` crate yourself, at version 0.12.0 in the manifest, and the crate is optional rather than mandatory.

Where Hayagriva is the wrong choice

The clearest case against it is a pipeline that already ends in a TeX compile. In that world a biblatex based workflow formats the bibliography during the typesetting run, where the engine already knows about the document context, cross references and the language of the surrounding prose. Hayagriva computes the same thing earlier, at runtime, in your own process, which is exactly what you want when there is no TeX engine in the picture and exactly what you do not need when there is.

A second limitation is that the library does not fetch anything. The YAML format has a slot for a DOI and the example data carries one, but nothing in the documentation describes resolving a DOI into metadata, contacting a metadata provider or keeping a bibliography file in sync with an online catalogue. If your workflow assumes that dropping in a DOI produces a filled-in reference, that expectation is not met by the documented features, and the metadata has to come from somewhere else, whether that is a manual file, a reference manager export or your own resolver.

A third is the style coverage question in reverse. Because over 2,600 styles live in the upstream CSL repository and only about 100 are bundled, an application that must render one specific uncommon style has to ship that style file itself and parse it with `IndependentStyle::from_xml`. That is easy for one style and awkward for a user-facing selector list, since each additional style in a dropdown becomes a file you maintain.

Editorial conclusion

Adopt Hayagriva if you are building a document tool or editor in Rust and need citations computed at runtime from YAML or Bib(La)TeX input, with the CSL style ecosystem available offline. Do not adopt it if your pipeline already ends in a TeX compile, because a biblatex based workflow formats the bibliography inside the typesetting run instead. Before you commit, verify that the style you need exists in the CSL repository or ships with the archive feature, confirm whether you can accept the MIT OR Apache-2.0 dual license of the crate, and check that the version constraint you write into your own Cargo.toml matches the 0.10 series rather than the 0.9 example printed in the project README.

Frequently asked questions

How do I install the Hayagriva command line tool?

Run `cargo install hayagriva --features cli`. The `cli` feature turns on the `clap` and `strum` dependencies and builds the `hayagriva` binary target.

Which citation styles does Hayagriva support?

It supports all styles provided in the official Citation Style Language repository, currently over 2,600. About 100 citation styles are bundled with the crate through the `archive` feature, and you can also supply your own CSL files.

Can Hayagriva read BibTeX files?

Yes. With the default features enabled, which include `biblatex`, Hayagriva supports BibTeX and BibLaTeX bibliographies and you can parse them with `io::from_biblatex_str`. Disabling default features removes that support.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. typst/hayagriva on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/typst-hayagriva.svg)](https://hysenlabs.com/projects/typst-hayagriva)