# Contributing to Copper Thank you for helping build a deterministic, production-ready robotics runtime. Contributions of code, components, documentation, examples, and careful bug reports are all welcome. ## Choose Where to Start | You want to… | Best next step | | --- | --- | | Ask a usage question | Search the [documentation](https://copper-project.github.io/copper-rs/) or ask on [Discord](https://discord.gg/VkCG7Sb9Kw). | | Report a bug or request a feature | Open the matching [issue template](https://github.com/copper-project/copper-rs/issues/new/choose). | | Propose a runtime or architectural change | Start a [Discussion](https://github.com/copper-project/copper-rs/discussions) before investing in a large implementation. | | Add a reusable driver, task, bridge, or payload | Read [Contributing Components](#contributing-components); an independent crate is often the best home. | | Improve docs or examples | Open a focused pull request and update related wiki/book material when behavior and documentation move together. | | Report a vulnerability | Follow the private process in [SECURITY.md](SECURITY.md). Do not open a public issue. | All community participation is governed by our [Code of Conduct](CODE_OF_CONDUCT.md). ## Set Up the Workspace Copper's minimum supported Rust version is 1.95. Install the latest stable Rust toolchain with [rustup](https://rustup.rs/), then install [`just`](https://just.systems/) and clone your fork: ```bash cargo install just git clone https://github.com/YOUR_USERNAME/copper-rs.git cd copper-rs ``` The Ubuntu development dependencies are documented in [`support/docker/Dockerfile.ubuntu`](support/docker/Dockerfile.ubuntu). Other platforms may require equivalent system packages.
One-time tools used by the full PR check The root `justfile` is the source of truth. Its checks use `cargo-nextest`, `typos-cli`, `taplo-cli`, `fmtron`, and `prek`: ```bash cargo install --locked cargo-nextest typos-cli taplo-cli fmtron prek ``` The public API check also pins a nightly toolchain and `cargo-public-api` version. Run `just api-check`; if either is missing, it prints the exact versioned install command required by the current repository. Coverage additionally requires `cargo-llvm-cov` and `llvm-tools-preview`: ```bash cargo install --locked cargo-llvm-cov rustup component add llvm-tools-preview --toolchain stable ```
## Contribution Workflow 1. Create a branch from `master` using `user/kind/description`, for example `alex/fix/replay-seek`. 2. Make one focused change. Add tests and update documentation or examples where the behavior needs them. 3. Run `just` from the repository root. It formats the workspace, runs lint and API checks, and tests the std and `no_std` surfaces. 4. Review the complete diff, then commit with a clear message. Conventional Commits are welcome but not required. 5. Push your branch and open a pull request to `master`. Explain the problem, the chosen approach, and how you verified it. The pull request template contains the final submission checklist. ## Checks Prefer the root `justfile` over copying long Cargo command lines: | Change | Run | | --- | --- | | Most pull requests | `just` or `just pr-check` | | Formatting, typos, and clippy only | `just lint` | | Host/runtime behavior across the std feature matrix | `just std-ci` | | Shared, embedded-facing, or `no_std` code | `just nostd-ci` | | Coverage-sensitive behavior | `just coverage` | | Runtime proc-macro expansion | `just expand-runtime pkg= bin= [features=]` | | SoA derive expansion | `just expand-soa` | Linux is the primary full-workspace gate. macOS is also release-blocking, Windows validates a reduced core surface, and embedded coverage is compile-time rather than hardware-in-the-loop. See [Supported Platforms](https://copper-project.github.io/copper-rs/Supported-Platforms) for the public platform matrix. ## Design Expectations Copper has a deliberately opinionated architecture. Contributions should preserve these properties: - **Static over dynamic:** prefer types, compile-time wiring, and generated code to runtime string lookup or mutable graph topology. - **Realtime paths stay lean:** do not add allocations, copies, serialization passes, or latency to the hot path without explicit design agreement. - **`no_std` is a real target:** shared crates, traits, and macros must not assume host-only APIs. - **Determinism and replay are product features:** runtime changes must preserve unified logging and reproducible replay. - **Use Copper's logs:** inspect recorded CopperLists and structured logs before adding ad hoc text instrumentation. - **Keep abstractions understandable:** solve the underlying design problem instead of hiding it behind runtime magic or invisible environment variables. When proc-macro behavior is unclear, use the expansion recipes above. When a runtime failure already has a `.copper` log, prefer extraction and resimulation before adding new instrumentation. ## Contributing Components Reusable components do not always need to live in this monorepo. For a driver, task, bridge, payload, or monitor, the preferred path is usually: 1. Publish it as an independent crate or repository so it can evolve on its own release cycle. 2. Document its supported targets, configuration, and usage as a standalone Copper component. 3. Add it to the [Copper Component Catalog](https://cdn.copper-robotics.com/catalog/index.html). Open an issue or Discussion first if the component must be maintained in the main workspace or changes a shared Copper interface.
Dependency changes Keep dependencies minimal and explain why each new dependency is required. Run `cargo shear` when changing manifests: ```bash cargo install --locked cargo-shear cargo shear ``` If `cargo-shear` flags a feature-gated or build-time dependency incorrectly, document the exception next to the affected package: ```toml [package.metadata.cargo-shear] # Required by build.rs for generated bindings. ignored = ["some-crate"] ```
Optional local commit hooks The repository's `prek` hooks run file hygiene, formatting, and typo checks: ```bash prek install -f prek run --all-files ``` Update `.pre-commit-config.yaml` if the shared hook configuration needs to change.
Maintainer release branches, versioning, tagging, and backporting are documented in [RELEASING.md](RELEASING.md).