Thanks for your interest in xrag. This document covers how to get set up, the checks we expect before review, and the conventions the PR template encodes.
xrag uses uv for dependency management and requires Python 3.11 or newer.
git clone https://github.com/henryle97/xrag.git
cd xrag
make sync # uv sync --group dev + the extras the tests need
make precommit-install # installs the pre-commit hooks (recommended)make sync installs the cli, chroma, and rerank-cohere extras because
the unit tests import them directly. A bare uv sync is not enough to run the
test suite.
Local PDF/OCR parsing is heavy and optional. Add it only if you're working on that path:
uv sync --group dev --extra cli --extra chroma --extra rerank-cohere \
--extra parser-unstructured-local-pdfCopy .env.example to .env and fill in only the keys you need. Every
variable maps to a field on xrag.config.settings.Settings. Unit tests are
hermetic and need no credentials.
Run these before opening a PR:
make lint # ruff check + ruff format --check
make unit-test # pytest tests/unit -q — hermetic, this is the CI gatemake check additionally runs compileall. Integration tests
(make integration-test) make real network calls, are not part of CI, and
require credentials.
After changing runtime behavior, also exercise the changed path with a live CLI command — unit tests alone don't prove a pipeline still runs end to end.
- Unit tests live in
tests/unit/and must stay hermetic — no network, no credentials, no reliance on files outside the repo. - Contract tests in
tests/contract/run against the built wheel and guard the public API surface. If you add or remove anything inxrag.__all__, update them. - Mark network-dependent tests with
requires_network,requires_qdrant, orrequires_openai.
Everything exported from xrag.__all__ is the supported surface and is
SemVer-bound. Anything outside it is internal. Changing an exported name is a
breaking change and needs a contract-test update plus a changelog entry.
The PR template asks for four things. Keep the shape:
- Problem — what's broken or missing
- Why — why it's worth changing now
- What changed — the actual diff, in prose
- What did NOT change — scope boundaries, so reviewers know where not to look
Include a Test plan with make lint and make unit-test checked, plus any
live CLI, integration, or manual verification you did. Skip the Risks section
entirely when there are none rather than writing "None".
Other expectations:
- Branch from an up-to-date
main:git checkout main && git pull --ff-only origin main - Keep PRs focused. Parent/child issues ship together as the parent's PR.
- Resolve review threads only after the fix is pushed.
- Don't auto-merge.
GitHub's auto-close parser only fires when a close keyword (Closes, Fixes,
Resolves) sits on the same content line as the issue reference. A heading like
## Closes followed by #19, #20, #21 silently closes nothing.
Write one close keyword per issue, each on its own content line:
Closes #19. Closes #20. Closes #21.
Verify before merging:
gh pr view <N> --json closingIssuesReferencesWe use Conventional Commits with a module scope:
feat(parser): add DocxPicturePartitioner
fix(config): reject unknown provider names
test(chunker): cover image chunk emission
docs(plans): refresh indexing backlog
Common scopes: parser, chunker, embedder, indexer, client, config,
eval, ci, packaging.
Check docs/adr/ before making architectural changes — it records
decisions that are easy to accidentally reverse. Add a new ADR when you change
a cross-module contract or reverse an existing decision.
Deeper domain context lives in CONTEXT.md and
docs/agents/domain.md.
Retrieval quality changes need evidence. The full discipline is documented in
CLAUDE.md; the short version:
- Run evals through
scripts/eval/, which writes toexperiments/eval/<config-stem>-<timestamp>/. - Append a new row to
docs/BENCHMARK.md— never edit existing rows. - Per-category
R@10is the primary regression signal. experiments/eval/experiments.jsonlis the append-only source of truth.
Benchmark documentation uses a fictional issuer and synthetic figures. Never
commit real customer documents, real financial data, or anything under data/
(it is gitignored for this reason).
Use the issue templates. For security issues, follow SECURITY.md instead of opening a public issue.