This file is for AI coding agents working in this repository. Humans, see
CONTRIBUTING.md.
A mixed Rust/Python monorepo: a pure-Rust core, a thin PyO3 FFI layer, and a
Python wrapper. Built with maturin + uv, tasks run through just.
crates/
├── rust-python-template-core/ pure Rust; #![forbid(unsafe_code)]; source of truth
└── rust-python-template-ffi/ PyO3 → rust_python_template._core; publish = false;
data conversion only, no business logic
python/rust_python_template/ user-facing Python wrapper + .pyi stubs
tests/rust/ cargo integration tests against -core
tests/python/ pytest against the FFI boundary
Hard rules:
-coreis#![forbid(unsafe_code)]. No unsafe, no exceptions. If you need unsafe interop, it goes in-ffiwith a// SAFETY:comment that states the invariants relied on.-corehas zero Python dependencies. It must compile and test without libpython.-ffidoes conversion only. Business logic must live in-core.- Stable Rust only. Channel is pinned by
rust-toolchain.toml. - The workspace
[lints]table deniesunwrap_used,expect_used,panic,todo,unimplemented,dbg_macro. If you reach for any of these, you are signaling that a real error type is missing.
Every workflow goes through just. CI mirrors these recipes 1:1.
| Recipe | What it does |
|---|---|
just bootstrap |
uv sync --all-extras + uv run maturin develop --release. Run once after clone. |
just develop |
Rebuild the FFI extension in debug mode (fast iteration). |
just build |
Build a release wheel into target/wheels/. |
just test |
Full suite: cargo nextest run --workspace then pytest. |
just test-rust |
Rust tests only. |
just test-py |
Python tests only. |
just lint |
cargo fmt --check, clippy -D warnings, ruff check, ruff format --check, pyright. |
just fmt |
Auto-fix: cargo fmt, ruff format, ruff check --fix. |
just audit |
cargo deny check (advisories, licenses, bans, sources). |
just clean |
Remove target/, .venv/, built _core*.so artifacts. |
just versions |
Print toolchain versions. |
- Rust:
cargo nextest run -p rust-python-template-core -- add_works - Python:
uv run pytest tests/python/test_add.py::test_add
rustupwith the stable channel (rust-toolchain.tomlenforces this).uv(Python + venv + dep management).just.cargo-nextest(cargo install cargo-nextest --locked).cargo-deny(cargo install cargo-deny --locked).
Architectural changes (public API, crate boundaries, build/release process)
start as a draft decision in docs/decisions/, not
as a PR. Read docs/decisions/README.md for
the lifecycle. When status is ready, the Decision is final; implement
it as stated — do not redesign mid-flight. If you find an unresolved
question while implementing a ready doc, stop and ask.
- Errors: use
thiserrorin-corefor typed errors.-fficonverts them toPyErrat the boundary. - Docs:
missing_docsis a warn-by-default lint. Every public item in-coreshould have a doc comment. - PyO3 version: 0.28 with
abi3-py310. One wheel covers Python 3.10–3.14. Do not pin a specific Python version. unreachable_pubis a warn lint; preferpub(crate)for items not in the public API.
CLI, fuzzing, benchmarks, reference-impl oracle, real-model integration
tests, mkdocs user docs, design docs, slow-tier CI workflow. See the
"Opt-in extensions" section of docs/decisions/README.md.
These are documented recipes, not promised features.