easa-erules
Deterministic, local toolkit for EASA Easy Access Rules — built for LLM agents.
Turns the official EAR XML exports (CS-*, AMC, GM) into structured data an agent can quote from. An experimental FAA branch serves 14 CFR through the public eCFR API using the same interface.
- fetch a regulation, or a pinned version, into a local cache
- parse into a canonical Regulation AST (Flat OPC / OOXML, or eCFR XML)
- export Markdown, JSON and HTML
- extract one rule, query with SQLite FTS5, walk cross-references
- validate conversions so nothing is dropped silently
Regulatory text is never rewritten by an LLM during conversion. Conversion is deterministic; models reason on tool output, not on recall.
Every machine-readable result states which publication and amendment it came from, and distinguishes "searched, found nothing" from "never looked" — the usual way an agent pipeline goes quietly wrong.
Install
Requires Python ≥ 3.11.
# PyPI (recommended for users)
pip install easa-erules
# or with uv
uv pip install easa-erules
From source / development:
git clone https://github.com/mrSpringpeace/easa-erules.git
cd easa-erules
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
# or: pip install -e ".[dev]"
Pinned git tag (if PyPI is unavailable):
pip install "git+https://github.com/mrSpringpeace/easa-erules.git@v0.3.0"
Optional MCP server (for agent hosts that speak MCP rather than shell):
pip install "easa-erules[mcp]"
Entry points: easa-erules, easa-erules-mcp.
Disclaimer: Unofficial toolkit, not endorsed by EASA or the FAA. Always verify critical interpretations against the official publication. The MIT licence covers this software only — see
NOTICEfor the attribution and licensing of regulatory text.
Quick start
# Catalog
easa-erules list
easa-erules info vla
# Download latest XML into the cache
easa-erules fetch cs-vla
easa-erules fetch cs-vla --version "Amendment 1"
easa-erules versions cs-vla --verify
easa-erules versions cs-vla --remote
easa-erules outline cs-vla --version amendment-1 --json
# Inspect / convert / extract / search / refs
easa-erules inspect cs-vla
easa-erules convert cs-vla -o ./out --split
easa-erules convert ./local.xml -o ./out --format html
easa-erules extract cs-vla CS-VLA.303 --format json
easa-erules query cs-vla "factor of safety" --material certification_specification --json
easa-erules refs cs-vla CS-VLA.303 --json
easa-erules validate ./out
# FAA parts work the same way (experimental)
easa-erules fetch far-23
easa-erules extract far-23 "14 CFR 23.2005" --format json
Local path or registry id/alias is accepted for most commands. Use --fetch on convert/extract/query when the id is not cached yet.
Output contract
Every --json result carries the same envelope, so an agent can branch on it
without guessing:
{
"schema_version": "1.1",
"status": "ok",
"source": {"regulation_id": "cs-vla", "amendment": "Amendment 1", "sha256": "…"},
"warnings": [],
"rule": { "…": "…" }
}
status |
exit | Meaning |
|---|---|---|
ok |
0 | Succeeded, results present |
no_match |
0 | Searched, nothing matched |
not_cached |
3 | Not downloaded — run fetch or pass --fetch |
index_missing |
4 | Search index damaged — retry with --rebuild |
fetch_failed |
5 | Download failed |
source_drift |
6 | Landing page no longer matches the catalog entry |
parse_error |
7 | Source could not be parsed |
integrity_error |
8 | Cached bytes do not match the stored SHA-256 |
error |
1 | Unknown id, bad path, everything else |
no_match is not evidence that a requirement does not exist. Amendment and
issue are never silently null: when they cannot be established the field reads
unknown and a warning says so.
Cache layout
~/.cache/easa-erules/ # override: EASA_ERULES_CACHE
cs-vla/
source.xml # latest convenience copy
meta.yaml
versions/<slug>/
source.xml
meta.yaml # sha256, download_url, retrieved_at, …
search.sqlite # schema v2; isolated per amendment
original.zip
Split convert output
out/
├── index.md
├── metadata.yaml
├── document.json
├── conversion-report.json
├── rules/
│ └── cs-vla-303.md
└── assets/
└── cs-vla-303-fig-01.png
CLI reference
| Command | Purpose |
|---|---|
list |
Built-in regulation catalog |
info |
Metadata + cache presence for an id/alias |
fetch |
Resolve landing page → download XML → cache + integrity |
versions |
Local/remote amendments, integrity/freshness, safe deletion |
outline |
Lightweight ordered navigation tree for a pinned version |
inspect |
Structure stats, warnings, unknown elements |
convert |
Markdown / JSON / HTML (--split, --format) |
extract |
Single rule (JSON preferred for agents) |
query |
Paginated/filterable FTS5 search and filter-only browse |
refs |
Outgoing / incoming cross-reference graph |
validate |
Check a conversion output directory |
Design principles, adapters and the full output contract: docs/MANUAL.md.
Architecture
EASA landing page ──fetch──► cache (XML + meta + sha256)
eCFR API ──fetch──► │
│
Local XML/DOCX ───────────────────┤
▼
OpcPackage / eCFR XML
▼
EasaDocumentParser | FaaEcfrAdapter
▼
Regulation AST ──normalize──►
▼
┌───────────────┼───────────────┐
▼ ▼ ▼
Markdown JSON HTML
│
├── SQLite FTS5 (query)
├── Reference graph (refs)
└── Validation / conversion-report.json
Built-in sources
EASA — sources/easa.yaml, keyed on stable landing pages rather than
fragile direct URLs:
cs-vla, cs-lsa, cs-22, cs-23, cs-25, cs-27, cs-29, cs-e, part-21, uas-rules
cs-p and cs-etso are catalogued but PDF-only — EASA publishes no XML
export for them, so commands fail with an explanation instead of a confusing
parse error.
FAA — experimental — sources/faa.yaml, served by the public eCFR API:
far-21, far-23, far-25, far-27, far-43, far-91
This branch is a prototype: it mirrors regulation text only, its shape may change, and it is not a source for the FAA certification basis. EASA is where this project is maintained.
A weekly workflow resolves, downloads and parses every entry, and reports drift without failing the build:
python scripts/catalog_health.py --deep
For LLM agents
Two integration routes, same results:
- Shell — the thin skills under
skills/(generic / Codex / Claude Code / OpenCode) - MCP —
easa-erules-mcp, exposing the catalog/version inventory, outline, filtered search, rule context, assets and legacy operations
Cookbook: examples/agent-cookbook.md
Full manual: docs/MANUAL.md
Rules of engagement:
- Prefer
query/extract/refswith--jsonover stuffing full regulations into context. - Never hand-write or "fix" regulatory text from model memory.
- After bulk
convert, runvalidate. - Ground answers only on tool output, and cite the
designation+amendmentfrom thesourceblock. - This is an EASA source. It is not a source for the FAA certification basis — the FAA branch mirrors eCFR text only, with no Advisory Circulars or policy material.
Development
pytest # offline; real-sample tests skip
python tests/real_samples/fetch_samples.py # pull the pinned publications
pytest -m real_sample -v
EASA_ERULES_LIVE=1 pytest -k live -v # network smokes
ruff check src tests scripts
- Unit fixtures:
tests/fixtures/ - Golden renders:
tests/golden/ - Real documents: pinned, not committed — see
tests/real_samples/README.mdanddocs/LEGAL-REVIEW.md
Development state: docs/STATUS.md
Design principles
- Deterministic conversion — same source + parser version → same AST/ids/exports
- No silent content loss — unknown elements and failed structures are reported
- AST in the middle — no direct XML → Markdown hacks
- Agent-first CLI — versioned, self-describing JSON for extract/query/refs
- Explicit over empty — a result never leaves an agent guessing why it is empty
License
MIT for the software — see LICENSE.
The MIT grant does not extend to regulatory text retrieved through this
tool. EASA Easy Access Rules are reproduced with acknowledgement per
EASA's copyright policy;
14 CFR is US Government work in the public domain. See NOTICE.
Release files for easa-erules 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 | |
|---|---|---|---|
| easa_erules-0.3.0.tar.gz | 164.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| easa_erules-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 299.9 kB
Release files / easa_erules-0.3.0.tar.gz
| Download URL | easa_erules-0.3.0.tar.gz |
|---|---|
| Size | 164.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2aeb749c8940f0808819c3771aa2c43c33d7762f95ad86fd4c34a2a6c92ec557
|
|
BLAKE2b-256 checksum How to use checksums |
2ce95f3f75a2a5b131a28968bf40cec94c23fa9e832ab8464b09dcecb1f6ee76
|
| 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 11, 2026.
Transparency logRelease files / easa_erules-0.3.0-py3-none-any.whl
| Download URL | easa_erules-0.3.0-py3-none-any.whl |
|---|---|
| Size | 135.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
87f05e917b9185b21edd7a39995377bc49945046740ee61eaf8065a2137700ee
|
|
BLAKE2b-256 checksum How to use checksums |
ea626659358dd5e058248b47358b533a4e0e4fbf6bfb62b30056220f34a2a77d
|
| 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 11, 2026.
Transparency log