This page describes what we expect from pull requests across the uutils
projects (coreutils,
findutils and the others) and how reviews
are carried out. It is meant for both contributors who want to know what a
reviewer looks for, and reviewers who want a shared checklist. Each
project's CONTRIBUTING.md links here; the rules below apply to all of them.
The one rule that cannot be bent
uutils is original code. We cannot accept any change based on the GNU source code, and you must not even link to the GNU source in an issue or PR. A reviewer will reject a contribution that appears to be derived from GNU (or any other strongly-licensed implementation such as GPL/LGPL code).
It is fine to look at permissively-licensed implementations (Apple's file_cmds, OpenBSD) and to read the GNU manuals and man pages - just never the GNU source.
What a reviewer expects before merging
A pull request is ready to be merged when it meets all of the following. If you check these before requesting a review, your PR will move much faster.
- It passes CI. The test suite is green (allowing for intermittently
failing tests),
rustfmtis satisfied, and there are noclippywarnings. - It compiles without warnings on every CI platform. Use
#[cfg(...)]for platform-specific code rather than breaking other targets. - It is small and self-contained. A series of small PRs gets merged far faster than one large one. Unrelated changes belong in separate PRs.
- It has a descriptive title. Describe the problem solved, e.g.
ls: fix version sort order, notFix #1234. Prefix with the utility name when relevant. - New behavior comes with tests. Our test suite is fast; regressions should be caught by a test. Code coverage should not regress.
- If possible, it was discussed first. For anything non-trivial, open (or comment on) an issue before writing the code, so effort isn't wasted on a change we can't merge.
- It follows GNU behavior for options and output, verified against the GNU manual or output - never the GNU source.
- GNU compatibility does not regress. The GNU test suite (
run-gnu-test.sh, tracked withremaining-gnu-error.py) should not go backwards; a compatibility fix should ideally add the now-passing test. Error messages and exit codes should match GNU, checked withLANG=C(except for locale bugs). - If the GNU test suite passes but you still found a behavior difference, that is a gap in their coverage: please contribute the missing test upstream to GNU to improve their test suite.
- It updates docs, help and translations. A new option or behavior should
also update the
--helptext, the documentation, the generated man pages, and at least the Englishlocales/en-US.ftlstrings. - It stays focused. Keep formatting-only changes, unrelated refactors, and dependency or lockfile bumps out of a feature or fix PR.
- It is safe with untrusted input. Utilities process arbitrary file contents and arguments, so avoid unbounded allocations, integer overflow, and path-traversal foot-guns.
- It does not regress performance. Runtime should not get more than 3%
slower than the current
main. Increased memory usage is acceptable when it is justified (e.g. it buys a meaningful speed-up or is needed for correctness). - It does not regress binary size. The compiled binary should not grow more
than 3% compared to the current
main, unless the increase is justified by the change. - New dependencies must be discussed and justified. Adding a crate is not
free - it affects build time, binary size, the audit surface, and licensing.
Raise it first, explain why it's needed and why an existing dependency or a
small amount of in-tree code won't do, and make sure its license is compatible
(see Licensing in each project's
CONTRIBUTING.md).
Commit hygiene reviewers care about
- Small, atomic commits with a clean history.
- Informative messages annotated with the component, e.g.
cp: do not overwrite with -ioruucore: add support for FreeBSD. - Don't move code around unnecessarily - it makes diffs hard to review. If a move is needed, do it in its own commit.
Coding expectations reviewers check against
- No
panic!- avoid.unwrap(),panic!and strayprintln!. A justifiedunreachable!needs a comment. - No
exit- utilities must be embeddable, so avoidstd::process::exitand friends. - Minimal
unsafe- generally only for FFI, always with a// SAFETY:comment. Performance is rarely a good enough reason. OsStr/Pathoverstr/Stringfor paths, since paths may not be valid UTF-8.- Macros sparingly, and comments that explain why, kept up to date.
- Don't silence clippy with
#[allow(...)]. In particular, we don't want to see#[allow(dead_code)]; fix the underlying issue (or remove the unused code) instead of suppressing the lint.
For contributors: getting your PR reviewed
- You don't need to ping a maintainer the moment you open a PR.
- If you get no response within a few days, it's fine to request a review.
- If after a week there's still no review, ping the maintainers on
Discord (
#coreutils-chatfor coreutils). - You know your code best - please resolve merge conflicts on your branch
yourself (
git merge mainorgit rebase main, your choice). Ask for help if you get stuck. - When you address review feedback, fold the fixes into the relevant commits
(
git commit --fixup/git absorb) to keep history clean.
For reviewers: how we review
- Double-check a human's work. A reviewer is there to verify a contributor's reasoning, not to launder unreviewed machine output. Expect the author to be able to explain and justify every line.
- Watch for GNU/GPL provenance. Be especially careful with AI-assisted patches: assistants are trained on GPL sources and can reproduce them verbatim, which we cannot accept.
- Keep comments short and actionable. Prefer simple, one-line comments on the specific line, so the author knows exactly what to change.
- Push back on long-winded code, duplication, needless complexity, and changes that arrive without tests.
- Confirm the basics from the checklist above (CI, scope, title, tests, style) rather than re-deriving them each time.
- Disregard machine-generated discussion. Review comments and replies should come from a person. Maintainers may hide or ignore comments that read as AI-generated.
AI-assisted contributions
AI-assisted contributions are allowed, but the same standards apply as for any other patch. If you use an AI tool, you are responsible for the result: you should understand every line, be able to justify it in review, and make sure the output is not derived from GNU or other GPL code. Keep patches small and self-review the diff carefully before opening the PR. Commit messages and PR descriptions should describe the change, not the tooling used to produce it.
AI is a tool for writing code. Issue reports, pull request descriptions, and replies to reviewers should be written in your own words. The whole point of review discussion is to confirm that a human understands the change; generated prose defeats that.
This is not about English fluency: if you are not a native speaker, using a tool to fix grammar or translate your own words is fine. The point is that the ideas and reasoning should be yours, not an AI's.
This section is inspired by the astral-sh AI policy and Mozilla's AI coding guidance.
See also
- The full
CONTRIBUTING.mdin each repository (coreutils, findutils) DEVELOPMENT.mdfor setting up your environment- Our Code of Conduct