We accept code, docs, bug reports, and feedback from anyone willing to file them clearly. This page covers the mechanics β how to get a change in, what we look for in review, and what to expect after you open a PR.
See Communication for non-code contributions (reporting issues, feedback, getting help).
See RFC process for larger changes that need design discussion before implementation.
For anything larger than a typo fix:
- Check the issue tracker. Someone may already be working on it or have filed a related discussion.
- Read
AGENTS.md. The repo's rootAGENTS.mdis the canonical source of convention β risk tiers, PR discipline, anti-patterns, and review standards live there. - Pick a branch. PRs target
master. Fork the repo and branch from there; there's no develop/integration branch to go through.
fork β branch β commit β push β open PR β review β merge (squash)
The key checkpoints:
- PR template β
.github/pull_request_template.md. Fill it out. The summary, validation evidence, and compatibility sections are non-negotiable. - CI β runs on every PR.
ci.ymlis the composite gate; all legs must pass. - Labels β scope (
scope:providers,scope:channels, etc.) and risk (risk:low/risk:medium/risk:high) are auto-applied by path-labeler. Double-check they match your change; if not, flag in a comment. - Review β maintainers review. Findings follow
[blocking]/[suggestion]/[question]tiers. Address blockers; suggestions are optional; questions need an answer.
cargo fmtclean (checked in CI)cargo clippy -D warningsclean (checked in CI)- No unused production code β delete it, wire it into behavior, or track a follow-up issue. Do not silence it with underscore prefixes or
#[allow(dead_code)]; reserve underscore names for required but intentionally unused API, trait, or callback parameters. - Error handling:
anyhow::Resultat binary boundaries, typed errors in library crates. Nounwrap()/expect()in production code paths β propagate with?or document the invariant that makes panic impossible. - Minimal dependencies β every dep adds to binary size; weigh the trade before adding one
- Trait-first β define the trait in
zeroclaw-api, then implement in the right edge crate - Security by default β allowlists, not blocklists. New external surface defaults closed
- Inline unit tests β
#[cfg(test)] mod tests {}at the bottom of the file or a siblingtests.rs - Don't commit secrets, personal data, or real-user identities β the Privacy & PII discipline page is the merge gate
- Unit tests co-located with the code (
mod tests) - Integration tests in
tests/and crate-local unit tests β run viacargo nextest run --locked --workspace --exclude zeroclaw-desktop - Feature-gated code needs feature-gated tests
- Don't mock the database for tests that exercise schema or SQL β integration tests must hit a real SQLite
For the full five-level taxonomy (unit / component / integration / system / live), shared mock infrastructure, and JSON trace fixture format, see Testing.
- Prose changes go in
docs/book/src/**/*.md(this mdBook) - Rustdoc (
///) changes update the API reference automatically on deploy - Reference pages (
docs/book/src/reference/cli.md,config.md) are generated β don't hand-edit. Runcargo mdbook refsand commit the output - Localisation β if you change user-facing strings, run
cargo mdbook syncto refresh the.pofiles
Conventional Commits:
feat(providers): add support for DeepSeek reasoning mode
fix(channels/matrix): prevent duplicate device sessions after verify
docs(getting-started): add YOLO-mode quick-start
refactor(runtime): split agent loop into steps
chore: bump tokio to 1.43
Co-authoring with AI is encouraged; add Co-Authored-By: trailers in commit messages where AI tools materially contributed. See FND-005 (Contribution Culture) for the full norm.
Title mirrors the squash commit:
feat(scope): short description
Body uses the PR template. The validation-evidence section is required β paste the output of cargo fmt --check, cargo clippy, cargo test, plus whatever manual verification you did. "It works on my machine" is not evidence.
Risk labels:
risk:lowβ rollback is a revert; no user action neededrisk:mediumβ users may need to update config / env / CLI usage; rollback plan requiredrisk:highβ security-critical, schema changes, breaking behaviour. Rollback plan, feature flag, and observable failure symptoms required
Merge strategy: squash-merge with the full commit history preserved in the body. See .claude/skills/squash-merge/SKILL.md for the exact format β TL;DR: PR title + (#number) as the subject, bullet list of original commits as the body.
Release: changes land on master; master does not auto-release. A maintainer bumps the version and tags vX.Y.Z when a release ships. You'll see your PR in the CHANGELOG.
| Area | Where to start |
|---|---|
| New channel | crates/zeroclaw-channels/ β copy an existing channel of similar shape |
| New provider | crates/zeroclaw-providers/ β compatible.rs covers most OpenAI-like ones |
| Docs | docs/book/src/ β anything marked outdated or missing |
| Translations | cargo fluent fill --locale <code> β see Maintainers β Docs & Translations |
| Hardware | crates/zeroclaw-hardware/ β new board support, new sensor drivers |
Don't be a jerk. Disagree on ideas; not people. Accept that maintainers will close things they don't want to own β usually with an explanation, occasionally without. If a close feels unjustified, ask; if the ask goes nowhere, move on.
- RFC process β for anything bigger than a patch
- Communication β how to reach the team
- Maintainers β Overview β what maintainers do day-to-day