Thanks for your interest in contributing to Cabin. This document covers local setup, required
checks, and PR workflow. The canonical crate-boundary, scope, and ownership rules live in
docs/architecture.md; do not duplicate them here.
- A recent stable Rust toolchain.
rustfmtandclippycomponents installed.taplofor TOML formatting.- For end-to-end build coverage: Ninja 1.10+, a C++ compiler (
g++,clang++, orc++), and a C compiler (gcc,clang, orcc) for tests that exercise.csources.
The unit tests in every crate, plus the resolution / lockfile integration tests, do not require Ninja or C/C++ compilers. The CLI build integration tests fail when those tools are missing, so install them before running the full suite.
git clone https://github.com/cabinpkg/cabin.git
cd cabin
cargo build --workspacecargo fmt --all --verbose -- --check
taplo fmt --check
typos
cargo clippy --workspace --all-targets --all-features --locked --verbose -- -D warnings
RUSTFLAGS="-D warnings" cargo check --workspace --all-targets --locked --verbose
RUSTFLAGS="-D warnings" cargo test --workspace --all-targets --all-features --locked --verbose -- --show-output
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features --no-deps --locked --verbose
# Conventional-commit lint of the commits this branch adds.
# Mirrors CI's @commitlint/config-conventional gate; every commit header
# must be a valid conventional commit and stay <= 100 chars.
npx --yes --package @commitlint/cli --package @commitlint/config-conventional \
commitlint --extends @commitlint/config-conventional --from origin/main --to HEAD --verboseThe Rust CI workflow runs the Rust commands above and treats warnings as errors; a separate CI job
runs the commitlint command above against the PR's commits. Mirror the flags verbatim when
running locally, including:
--all-featureson bothcargo clippyandcargo doc- cabin gates several modules behind features, and dropping the flag hides lints and broken intra-doc links that CI still fires on;- the trailing
-- -D warningsoncargo clippy(theclippy::pedanticgroup is denied workspace-wide via[workspace.lints]in the rootCargo.toml, so it no longer needs a command-line flag); - the
RUSTFLAGS="-D warnings"environment variable oncargo check/cargo test, which holds the macOS- and Windows-specificcfgcode to the same warning-free bar the Linux-onlyclippyjob enforces for everything else (CI sets it for every job; Cargo caps lints for registry dependencies, so only the workspace crates are held to it); - the
RUSTDOCFLAGS="-D warnings"environment variable oncargo doc, so broken or redundant docs links fail locally rather than only in CI; --locked, which pins the resolution to the committedCargo.lock. Reviewers will reject PRs that silently bump transitive dependency versions.
The repository's typos.toml pins the project locale to American English; do not modify it
(including adding new extend-words entries) unless a reviewer explicitly asks for the change. If
typos flags a spelling, fix the offending occurrence instead of allowlisting it.
The separate CI workflow also runs workflow linting and commit-message linting. Commit subjects are
validated with commitlint against @commitlint/config-conventional, so every subject must follow
Conventional Commits (<type>(<scope>)?: <subject>,
lower-case subject, <= 100 characters). Body and footer lines, if present, must also stay <= 100
characters per line.
The test suite includes external-tool smoke tests for ninja, clang-format, run-clang-tidy, and
pkg-config. Those tests fail when the real tools are missing, so install them to run the suite.
The pkg-config and run-clang-tidy smoke tests are #[ignore]d on Windows, where those tools are
unavailable.
- Idiomatic Rust. Prefer simple, direct code over clever abstractions.
- Follow the diagnostic and crate-boundary rules in
docs/architecture.md. - Avoid
unwrap()/expect()outside of tests except where invariants are obvious and locally proven. - Public APIs stay small. Add a doc comment when the reason a type or function exists is not obvious from its signature.
- Tests live next to the code they exercise. CLI integration tests live in
crates/cabin/tests/cli.rsand exercise the compiledcabinbinary viaassert_cmd. The user-facing example projects underexamples/are exercised bycrates/cabin/tests/cabin_examples.rsusing the same pattern. When adding or changing tests, follow the test portability rules incrates/AGENTS.md(env isolation via the sharedcabin()helper, tool-availability gating, and no host-specific absolute paths).
Read docs/architecture.md before changing crate boundaries, command
ownership, scope, diagnostics, generated formats, or build / registry / resolver behavior. When in
doubt, the architecture document wins.
- Keep PRs focused. One change per PR is easier to review and to revert.
- Add tests for behavior changes. New workspace, resolver, or build logic should land with unit
tests in the owning crate plus a CLI integration test in
crates/cabin/tests/cli.rs. - Update documentation when architecture or behavior changes. Update the relevant
docs/page. If you move code across crates, updatedocs/architecture.mdand the relevantAGENTS.mdrouting file. - Update the website when user-facing positioning changes. Copy on
website/(taglines, supported languages, supported platforms, top-level command surface, package-page install snippet) does not auto-regenerate from the Rust crates. A change that adjusts what Cabin is, what it builds, or how a user installs / declares / publishes a package must updatewebsite/in the same PR. SeeAGENTS.mdandwebsite/AGENTS.mdfor the docs/website checklist.
If you are unsure whether something belongs to the current scope, open an issue first or ask in the PR description rather than implementing it.