Reference Python client for the rrxiv protocol.
Project description
rrxiv-python
Reference Python implementation of the rrxiv protocol — parser, client SDK, FastAPI reference server, conformance test suite, and CLI.
Status: v0.1 — on PyPI (pip install rrxiv) and running in production at api.rrxiv.com.
Installation
Install from PyPI (the quotes on the extras are required so the shell doesn't try to glob the brackets):
# Library + parser only
pip install rrxiv
# Author CLI (login + submit): adds keyring credential storage
pip install "rrxiv[cli]"
# Agent identity (Ed25519 request signing, RFC 9421)
pip install "rrxiv[agent]"
# Reference server (FastAPI, uvicorn, ed25519 signatures, sentry, etc.)
pip install "rrxiv[server]"
Extras compose — an author who also runs an agent wants rrxiv[cli,agent].
Or with uv:
uv add "rrxiv[server]"
Quick tour
Parse a paper
rrxiv parse paper/main.tex --output paper.cir.json
rrxiv validate paper.cir.json
Produces a Canonical Intermediate Representation — paper metadata + claims + annotations + claim-graph edges, validated against the JSON Schema in random-walks/rrxiv.
Diff two CIRs locally
rrxiv diff before.cir.json after.cir.json # human-readable summary
rrxiv diff before.cir.json after.cir.json -f json # structured output
Semantic diff between two CIR documents: added/removed/changed claims, edge and citation deltas, annotation deltas, and top-level field changes (environment-specific fields like submitted_at are ignored). Useful for checking what a revision actually changes before submitting it. This is purely local — distinct from the server-side RevisionDiff that an instance computes when you submit a revision with rrxiv submit --revision-of <prior_paper_id> (or query GET /papers/{id}/diff?from=<prior>).
Run a local instance
# Memory store (lost on exit) — fastest path to play with the API
rrxiv serve --dev-mode
# Persistent SQLite store with a seed corpus
rrxiv serve \
--store sqlite:////tmp/rrxiv.db \
--seed-dir ./seed \
--port 8765
http://127.0.0.1:8765/api/v0/docs then shows the full OpenAPI; /api/v0/papers lists the seeded corpus.
Bulk-load a corpus
# First boot: seed a fresh DB from a directory of *.cir.json + *.pdf
# + *.source.tar.gz triples
rrxiv seed-store --from ./seed --store sqlite:////data/rrxiv.db
# When claim ids change between releases, --reset wipes the corpus tables
# before re-seeding so no orphan rows linger (dev-only: also drops any
# externally submitted papers + all annotations)
rrxiv seed-store --from ./seed --store sqlite:////data/rrxiv.db --reset
# On a LIVE instance, --preserve-community refreshes only the seed papers
# and keeps every externally submitted paper + all annotations
rrxiv seed-store --from ./seed --store sqlite:////data/rrxiv.db --preserve-community
seed-store also stamps paper.source.uri / paper.source.rendered_pdf_uri with the canonical /api/v0/papers/{id}/{source,pdf} endpoints so the web client can resolve them.
Package layout
rrxiv.models— Pydantic v2 models generated from the JSON Schemas (Paper,Claim,Annotation,Citation,CIR, plus enums).rrxiv.parser—.tex→ CIR. Recognises therrxiv.cls\claim/\evidence/\dependsonmarkup.rrxiv.client— async + sync HTTP client + retry policy + signature middleware.rrxiv.server— FastAPI app factory + 8 routers (auth, papers, claims, annotations, snapshots, search, submissions, sources). PluggableStore(memory / sqlite / future Postgres).rrxiv.testing—live_serverpytest fixture for running the server against real HTTP.rrxiv.cli— Typer CLI:- Authoring:
parse,validate,diff,submit,snapshot,doctor. - Auth:
login(ORCID / agent / anonymous flows, keychain persistence). - Ops:
serve,seed-store. - Read:
version,papers {list,get,versions},claims {list,get,top},search— added in Sprint 19 so the CLI is a first-class read client, not write-only. - Annotations:
annotation {validate,post,list,retract,replicate,comment,post-batch}—post-batchhitsPOST /annotations/bulk(up to 100 per request, single rate-limit unit).
- Authoring:
tests/— 400+ unit tests + the live cross-conformance test (test_server_cross.py) that runs the protocol-level test suite against the in-process server.
Development
uv sync --all-extras
uv run pytest # 400+ passed, ~4 skipped
uv run ruff check .
uv run mypy src/
Reference server in production
The Fly.io deployment that powers api.rrxiv.com lives in a separate private repo, rrxiv-instance — it pins a specific rrxiv-python commit, layers on the production Dockerfile + Fly config, and bakes the canonical 9-paper seed corpus into the image. The split is intentional: rrxiv-python stays a library anyone can fork to spin up their own instance; the canonical instance's operational concerns (CORS allowlist, ORCID redirect URIs, Sentry DSNs) belong to the overlay.
If you want to run your own rrxiv instance, fork that repo's structure — don't depend on its config.
Schema sync
Schemas live canonically in random-walks/rrxiv. We vendor them under src/rrxiv/_schemas/ and regenerate Pydantic models from them.
When the canonical schemas change (a new field, a tightened enum, a new schema file), run:
./scripts/sync_schemas.sh # default: ../rrxiv/schema (workspace pattern)
./scripts/sync_schemas.sh /path/to/schema # explicit path
./scripts/regen_models.sh # regenerate src/rrxiv/models/_generated/
sync_schemas.sh writes src/rrxiv/_schemas_manifest.txt with the source path, git SHA, branch, and timestamp so you always know which version of the protocol the vendored schemas correspond to.
regen_models.sh uses datamodel-code-generator (a dev dep, declared in pyproject.toml) to emit one Pydantic v2 module per schema into src/rrxiv/models/_generated/. The hand-written src/rrxiv/models/__init__.py re-exports the public surface so from rrxiv.models import Paper, Claim, CIR, ... keeps working when the generator output rearranges itself.
The cross-test in tests/test_models.py loads every fixture from ../rrxiv/tests/schemas/fixtures/ and checks that pydantic agrees with ajv on each. If the two diverge (a fixture passes ajv but fails pydantic, or vice versa), CI fails — that catches both codegen bugs and silent schema drift.
License
MIT (code) — see LICENSE. The protocol spec + schemas in random-walks/rrxiv are CC-BY-4.0.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rrxiv-0.2.0.tar.gz.
File metadata
- Download URL: rrxiv-0.2.0.tar.gz
- Upload date:
- Size: 719.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
612a1b16479b81d316aaec12eb1182118e45157dc1d81d1460f43c9a166918eb
|
|
| MD5 |
5773401a3f271269243dc2ea1fa61c7c
|
|
| BLAKE2b-256 |
a8ca4e602f51512241bd21e60cde7a33aac0da5c3fa2367407346d47600e8502
|
Provenance
The following attestation bundles were made for rrxiv-0.2.0.tar.gz:
Publisher:
release.yml on random-walks/rrxiv-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rrxiv-0.2.0.tar.gz -
Subject digest:
612a1b16479b81d316aaec12eb1182118e45157dc1d81d1460f43c9a166918eb - Sigstore transparency entry: 2169449712
- Sigstore integration time:
-
Permalink:
random-walks/rrxiv-python@7f32500f8d9b4c9b3c007505433ba3d6b2c82542 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/random-walks
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7f32500f8d9b4c9b3c007505433ba3d6b2c82542 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rrxiv-0.2.0-py3-none-any.whl.
File metadata
- Download URL: rrxiv-0.2.0-py3-none-any.whl
- Upload date:
- Size: 309.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65fe4456b301bd5fe390b1f5ef2738d54f060d8a4c68bda2b4f554b1169a598d
|
|
| MD5 |
c00bd2b122765316de466fe61b051d81
|
|
| BLAKE2b-256 |
7631a3b5643d832f33bc06beef7d48e14670c8ee5c757c052568bd879a7e128f
|
Provenance
The following attestation bundles were made for rrxiv-0.2.0-py3-none-any.whl:
Publisher:
release.yml on random-walks/rrxiv-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rrxiv-0.2.0-py3-none-any.whl -
Subject digest:
65fe4456b301bd5fe390b1f5ef2738d54f060d8a4c68bda2b4f554b1169a598d - Sigstore transparency entry: 2169449724
- Sigstore integration time:
-
Permalink:
random-walks/rrxiv-python@7f32500f8d9b4c9b3c007505433ba3d6b2c82542 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/random-walks
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7f32500f8d9b4c9b3c007505433ba3d6b2c82542 -
Trigger Event:
push
-
Statement type: