erga
Keep a website's academic publications list current, automatically, without giving up control of the data.
Status: alpha (v0.3). The CLI pipeline works end-to-end and its output has converged with a production lab site's existing pipeline in a parallel run against live OpenAlex (187/187 records, zero field diffs). That site now builds its publications with erga in CI. The JSON schema may still change before v1.0.
What it does
You list your authors (ORCID iDs) in one config file. erga fetches their works
from OpenAlex, normalizes and deduplicates them across registrars (arXiv,
Zenodo, publisher records), applies your curation files, and writes a
canonical publications.json into your site repository. Your site (Jekyll,
Astro, Hugo, anything) renders it however it likes.
- Curation that survives refresh: manual additions, per-record overrides, and highlights live in their own files and are re-applied on every automated run.
- Proper APIs, no scraping: OpenAlex (CC0 data) plus Crossref venue backfill, with API etiquette built in (keys, delays, retries).
- Git-owned data: the output is a diffable, PR-reviewable file in your repo: no hosted embed, no runtime dependency, publications present in the initial HTML.
- Delivery: a pip-installable CLI, or a GitHub Action. One workflow file plus one config file is the whole setup.
The name: έργα, "works" — the same term OpenAlex uses for publications.
Usage
Install with uv tool install erga or pip install erga (or run one-off
with uvx erga). Write an erga.yml:
mailto: you@example.org # identifies requests to Crossref/OpenAlex
authors:
- name: Josiah Carberry
orcid: 9999-9999-9999-9999 # placeholder: no real iD starts 9999
- name: Another Person
openalex_id: A5000000000 # alternative when ORCID is missing/wrong
openalex:
api_key_env: OPENALEX_API_KEY # optional; env var name, never the key itself
output:
path: publications.json
Then:
erga build [--config PATH] [--dry-run]runs the pipeline and writespublications.json. With--dry-runit prints a summary (fetched, merged, deduplicated, excluded, backfilled) without writing.erga verify [--config PATH]prints the author-disambiguation report: what each configured author resolves to on OpenAlex, with warnings for split profiles, zero-work authors, and implausible works counts. Run it once when setting up, and whenever a build looks off.
Run erga verify before your first build, because an ORCID does not
reliably identify one person on OpenAlex. The same iD can appear on several
profiles when it has been mistyped or copied into submissions, and erga
tracks all of them, so a wrong iD shows up as a pile of strangers' papers
rather than as an error. The report tells you what you are about to fetch.
GitHub Action
The action runs the build and stops there. It writes publications.json and
leaves delivery to your workflow, so you compose it with whatever you already
use to commit or open pull requests.
- uses: actions/checkout@v5
- uses: belalik/erga@v0.3.0
with:
version: "0.3.0" # pin explicitly; no default
config: _data/erga.yml
api-key: ${{ secrets.OPENALEX_API_KEY }} # optional
Paths inside the config resolve against the config's own directory, so
putting erga.yml where the site wants its data is usually the whole
configuration: _data/erga.yml writes _data/publications.json.
Recipe 1, commit back inside your build workflow. The default, and what
the origin site runs. Because the build happens in the same job, it sidesteps
the rule that pushes made with GITHUB_TOKEN never trigger another workflow.
permissions:
contents: write
steps:
- uses: actions/checkout@v5
- uses: belalik/erga@v0.3.0
with:
version: "0.3.0"
config: _data/erga.yml
api-key: ${{ secrets.OPENALEX_API_KEY }}
- run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add _data/publications.json
git diff --cached --quiet || git commit -m "Update publications"
git push
# ...then build and deploy the site as usual, in this same job.
Recipe 2, open a pull request. The right default when you want a review gate, and the only clean path on a protected branch. Repeated runs update one branch and one PR, so quiet weeks produce no noise, and merging is an ordinary push that fires your deploy workflow.
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v5
- uses: belalik/erga@v0.3.0
with:
version: "0.3.0"
config: _data/erga.yml
api-key: ${{ secrets.OPENALEX_API_KEY }}
- uses: peter-evans/create-pull-request@v7
with:
commit-message: Update publications
branch: erga/publications
title: Update publications
Inputs, permissions, scheduling and version-pinning notes: docs/action.md.
Curation
Three optional curation files next to the config survive every refresh:
manual.yml (records the APIs miss), overrides.yml (per-record patches,
exclusions, dedup exemptions), and tags.yml (tag name to DOI/id lists;
tag semantics are entirely yours). The full schema and pipeline design live
in docs/requirements-v1.md.
License
MIT
Release files for erga 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| erga-0.3.0.tar.gz | 91.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| erga-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 118.6 kB
Release files / erga-0.3.0.tar.gz
| Download URL | erga-0.3.0.tar.gz |
|---|---|
| Size | 91.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
07cb3aae0f8e1ebb1d23f5793807ca03387d6b853d111d55b9e0b5e8227a9bae
|
|
BLAKE2b-256 checksum How to use checksums |
2fed2d1ed2cf623daa4c86e5b17bf2cbe67eeb0ae04cada81b4377e61233a909
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.
Transparency logRelease files / erga-0.3.0-py3-none-any.whl
| Download URL | erga-0.3.0-py3-none-any.whl |
|---|---|
| Size | 27.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fb41e1b3845a1a21feb3dedd006e5288e474cc4fcdfbe89751f17291a909a846
|
|
BLAKE2b-256 checksum How to use checksums |
fcf36f788a88e208a1b336a68cdc716fcf25f58283bd763574ed9b5b6811abcf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.
Transparency log