uutils coreutils, the 0.x Rust rewrite that ships by default on Ubuntu 25.10
Cross-platform Rust rewrite of the GNU coreutils
At a glance
- What is it?
- uutils coreutils reimplements the GNU coreutils in Rust for Linux, macOS, BSD, Windows and WASI, and every program is implemented. Some options are still missing, and the version numbers have not reached 1.0.
- Who is it for?
- uutils coreutils earns a place when you need the same commands on Windows, macOS or WASI and cannot ship GNU binaries, or when you need GNU-identical stderr from existing scripts. It is the wrong choice when your scripts lean on a long tail of rarely used flags, since the README states options may be missing without naming which ones, and when you need manpages and shell completions from a Cargo install, which leaves them out.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- uutils/coreutils24,367 ★ · +215
| Repository | 2026-09-22 | 2026-11-14 |
|---|---|---|
| uutils/coreutils | 24.2k | 24.4k |
215 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The caret diagnostic only appears when stderr is a terminal
At a terminal, a parse error is rendered as a compiler-style report with a caret under the argument at fault, where GNU prints a single line. Piped into another program, the same error comes out as the plain GNU message.
That split is deliberate, and it is the reason you can adopt these utilities without rewriting the scripts that parse their stderr. A shell script reading ls output through a pipe gets GNU's format. A person at a prompt gets the caret.
The mechanism is visible in Cargo.toml. Diagnostics rewrite ariadne's output by row number, so the workspace keeps the ariadne requirement at "0.6.0", tight enough that only patch releases arrive, with a comment saying a release that changes the shape of a report counts as a breaking change here, and names the uucore test the_rendered_report_has_the_row_shape_the_rewriting_assumes as the thing that catches it. A dependency bump that only patches ariadne can still move your error output.
main is at 0.13.0 while the newest tag is 0.12.0
Three tagged releases sit close together: 0.10.0 on 2026-08-05, 0.11.0 on 2026-08-31, and 0.12.0 on 2026-09-17. Seventeen to twenty-six days between them.
The workspace version in Cargo.toml is already 0.13.0. Cloning main therefore gives you code one version ahead of the latest tagged release, which matters because bug reporters are asked to use the binary from the latest commit rather than the latest tag. The reverse applies to product builders: the latest stable tag is the one offered for reproducible builds and for packagers.
None of these numbers reach 1.0, so the stability guarantee that normally arrives with a 1.0 tag does not apply. Worth noting for your own release planning: the stated bar is exact equivalence with GNU on stdout and on error code, and differences with GNU are treated as bugs. That bar is measured against GNU, not against the previous release of this project.
cargo install drops the manpages and the completions
Start from a clone:
git clone https://github.com/uutils/coreutils
cd coreutilsCargo is the quicker of the two build routes, and the process matches any other Rust program. It produces a multicall, BusyBox-type binary named coreutils:
cargo build --releaseInstall it with:
cargo install --path . --lockedThat places the utilities in Cargo's bin folder, for example $HOME/.cargo/bin. It does not install the files needed for shell completion or for manpages. If your users expect tab completion or expect `man ls` to resolve, the Cargo route leaves you short, and GNU Make is the route that fills the gap.
Building the binaries needs Rust, meaning cargo and rustc. GNU Make is optional for that, and required once you want the full package including all documentation on a Unix platform.
coreutils-*-musl is the escape hatch when glibc is too new
Prebuilt binaries are published from the main branch at the latest-commit release tag, with manpages and shell completions attached. They come in two libc variants, and the choice is not cosmetic.
The minimal compatible glibc version matches the ubuntu-latest runner. A binary from the coreutils-*-gnu variant therefore will not start on a system with an older glibc, and the symptom is a loader failure before main runs rather than a message from the utility. For a distribution or a container on an older base image, the answer is the coreutils-*-musl build, which does not carry that floor.
Two build-time switches change what gets linked. Setting OPENSSL_NO_VENDOR=1 links dynamically against the system libcrypto rather than statically linking a vendored copy, and MinGW on Windows additionally needs OPENSSL_STATIC=0. On MSVC the aws-lc backend is used, where AWS_LC_SYS_NO_JITTER_ENTROPY=1 is recommended to shrink the binary.
One multicall binary, or one Cargo package per utility
The default build gathers the most portable common set of utilities into a single multicall binary named coreutils, which is the BusyBox shape: one file, behaviour chosen by the name it is invoked as. The repository carries a .busybox-config file at the root alongside it.
Packagers who cannot ship one large executable take the other branch. Each utility lives in its own Cargo package named uu_UTILNAME under src/uu, selected by package:
cargo build -p uu_base32 -p uu_cat -p uu_echo -p uu_rmTo shrink the binary rather than split it, name the utilities and drop the defaults:
cargo build --features "base32 cat echo rm" --no-default-featuresOn the comparison with BusyBox itself, the README names only that shape and stops. What the project commits to is platform spread: the same utils on Linux, macOS, BSD, Windows and WASI, with --profile=release-small available when binary size is the constraint.
Makefile hands every target to gmake, so BSD make will not do
The root Makefile is four lines. It sets UseGNU=gmake $*, then routes both the all target and .DEFAULT through that variable, which forwards everything to gmake.
The consequence is concrete on macOS, where the make on PATH is BSD make rather than GNU make. Running make there will not build this project. You need gmake installed and on PATH first, which is a step the Cargo route does not ask for.
That short file is only a dispatcher. The real targets live in GNUmakefile next to it. Both sit at the repository root alongside Cargo.toml, Cargo.lock, Cross.toml for cross compilation, deny.toml for dependency policy, and build.rs. The Make route is also what produces the documentation, which is why the complete package needs Cargo and GNU Make together.
Every program is implemented, and some options are still missing
The README opens with a claim and its caveat in the same sentence: all programs have been implemented, but some options might be missing or different behavior might be experienced. That caveat is the part to plan around.
If a script of yours depends on an obscure flag, the most direct way to find out is to run it and diff the result.
Two feature flags mark where the optional machinery begins. SELinux support, covering chcon and runcon, needs libselinux and libclang installed before building with unix,feat_selinux. The openssl feature replaces the pure-Rust digest crates with OpenSSL's libcrypto across md5sum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum and cksum, and the README says the speedup is largest on CPUs without SHA-NI acceleration.
Editorial conclusion
uutils coreutils earns a place when you need the same commands on Windows, macOS or WASI and cannot ship GNU binaries, or when you need GNU-identical stderr from existing scripts. It is the wrong choice when your scripts lean on a long tail of rarely used flags, since the README states options may be missing without naming which ones, and when you need manpages and shell completions from a Cargo install, which leaves them out. Verify two things before switching: run your real scripts against the binary and diff the stderr, and check your target glibc against the ubuntu-latest floor, switching to the musl build if yours is older.
Frequently asked questions
What are the differences between uutils and coreutils?
uutils coreutils is a cross-platform reimplementation of the GNU coreutils written in Rust. All programs have been implemented, but some options might be missing or different behavior might be experienced, and the project treats differences with GNU as bugs.
how to use uutils coreutils
Build it with Cargo, which on most Rust-supported platforms produces a multicall BusyBox-type binary named coreutils, or build separate binaries per utility. Installing with cargo install --path . --locked puts the result in Cargo's bin folder, for example $HOME/.cargo/bin.
how to use coreutils on windows
Build with the windows feature using cargo build --release --features windows. There is also a unix feature, and a WASI build that uses the wasm32-wasip1 target with --no-default-features and feat_wasm.
how to install coreutils in ubuntu
On Ubuntu 25.10 and later there is nothing to install, because uutils coreutils ships by default. Elsewhere, install it from Cargo with cargo install --path . --locked, or build it from source with cargo build --release.
Official sources
Where developers are discussing it
Posts on Hacker News, dev.to and Lobsters that link to this repository, found by our scan of those communities. 1 in the last 30 days; newest first.
- Ubuntu 26.10 Finishes the Rust Coreutils Switch. What Should Developers Test?dev.to · Oct 21, 2026 · 6 points · 0 comments
- Rust coreutils acknowledges copying of GNU GPL codeHacker News · Sep 29, 2026 · 5 points · 1 comments
- Rust coreutils acknowledges copying of GNU GPL codeHacker News · Sep 17, 2026 · 7 points · 3 comments
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/uutils-coreutils)Star history chart for your README
[](https://hysenlabs.com/projects/uutils-coreutils)Was this useful?