uutils/coreutils: a Rust rewrite of the GNU coreutils for Linux, macOS and Windows
Cross-platform Rust rewrite of the GNU coreutils
At a glance
- What is it?
- uutils/coreutils reimplements the GNU command line utilities in Rust and ships one multicall binary. It solved the portability problem, but the README still admits that some options are missing or behave differently.
- Who is it for?
- Adopt uutils/coreutils if you need the same utilities on Windows, macOS, Linux or WASI, or if you are packaging for a distribution that already ships it, as Ubuntu has since 25.10. Do not adopt it if your scripts depend on exact GNU output and you have not diffed the two.
- 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 September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The portability problem uutils/coreutils was written to solve
GNU coreutils is a Linux project. The utilities assume POSIX behaviour, GNU libc and a Unix filesystem, so a script that calls `ls`, `rm` or `sha256sum` cannot simply be copied to Windows. The usual workarounds are Cygwin, WSL or MSYS2, each of which brings a compatibility layer that changes how paths, permissions and line endings behave.
uutils/coreutils takes a different route: it reimplements the utilities in Rust, so the same source compiles for Linux, macOS, BSD, Windows, WASI and other targets. The README states the aim is to work on as many platforms as possible so scripts can be transferred between them. The audience is therefore not the average Linux user, who already has GNU coreutils. It is cross-platform developers, packagers and anyone maintaining shell scripts that have to run in more than one operating system.
The project's stated goal is a drop-in replacement, and it treats differences from GNU as bugs. That framing matters when you evaluate it. You are not being sold a better `ls`. You are being sold the same `ls` on a machine that would otherwise not have one.
One multicall binary, many uu_* packages
The default Cargo build produces a single multicall binary named `coreutils`, in the BusyBox style. The binary inspects the name it was invoked under and dispatches to the matching utility, which is why one artefact can stand in for dozens of commands.
Internally the repository is a workspace. Each utility lives in its own package named `uu_UTILNAME`, and the top-level `Cargo.toml` exposes features that decide what goes into the binary. There are OS shortcodes (`unix`, `windows`), a default set (`feat_common_core`, `feat_diagnostics`) and opt-in features such as `openssl`, which routes the checksum utilities through libcrypto instead of pure-Rust digest crates.
That layout gives you three build shapes. A full multicall binary for the platform, a trimmed multicall binary with only the utilities you name, or a directory of individual binaries built with `--bins --workspace`. The trade-off is build time and binary size against convenience. A trimmed binary is smaller but you have to maintain the utility list yourself, and a missing utility only shows up when a script calls it.
Installing uutils/coreutils from source and running a first command
The README documents building from source rather than a package manager install, so start by fetching the repository. Both commands below are copied from the README.
git clone https://github.com/uutils/coreutils
cd coreutilsA plain Cargo release build then produces the multicall binary. The README notes that this builds the most portable common core set as a BusyBox-type binary named `coreutils`.
cargo build --releaseIf binary size matters more than speed, the README gives `--profile=release-small` as the replacement for `--release`. For platform-specific utilities you add a feature, for example:
cargo build --release --features windowsTo build only a handful of utilities into the binary, combine `--features` with `--no-default-features` and list the names:
cargo build --features "base32 cat echo rm" --no-default-featuresThe README also documents a GNU Make path for people who prefer it, including `make PROFILE=release` and `make SKIP_UTILS='UTILITY_1 UTILITY_2'` to exclude utilities from the build. If you would rather not build at all, the project publishes prebuilt binaries, manpages and shell completions from the main branch, and a latest stable tag for reproducible packaging. There is also a WebAssembly playground on the project site for trying the utilities in a browser. The README does not document a rollback procedure for a replaced system coreutils, which is worth noting before you overwrite anything.
Where uutils/coreutils diverges from GNU, and when that matters
The README is unusually direct: while all programs have been implemented, some options might be missing or different behaviour might be experienced. That sentence is the whole risk profile of the project. A script that uses only the common flags will usually be fine. A script that depends on an obscure GNU option, on a specific error message, or on the exact exit code of a failure path may not be.
The project's own answer is to treat differences as bugs, and to require matching stdout and exit codes. It also documents one deliberate extension: at a terminal, a parse error is rendered as a compiler-style report with a caret under the offending argument, while scripts and pipes still receive the plain GNU message. That is a real divergence in stderr, but it is gated on whether the output is a terminal, so pipelines are unaffected.
Performance is the other place where the goals are explicit. The README says significant slowdowns relative to other coreutils implementations are treated as bugs, and the `openssl` feature exists because the pure-Rust digest crates are slower than libcrypto on CPUs without SHA-NI acceleration. If you are checksumming large volumes on older hardware, that build flag is the difference between a usable and an unusable tool.
The wrong tool case is narrow but real. If you are on Linux, depend on GNU-specific behaviour, and have no cross-platform requirement, uutils/coreutils adds a compatibility surface for no benefit. The same applies to a hardened system where replacing coreutils would invalidate an existing security review.
BusyBox and GNU coreutils are the alternatives, and neither is equivalent
The closest alternative in packaging terms is BusyBox. It also ships a multicall binary, and the project lists busybox among its topics, which invites the comparison. The difference is in intent. BusyBox targets small and embedded systems and implements a reduced set of utilities with reduced option coverage, often with its own `ash` shell alongside. uutils/coreutils targets desktop and server platforms and aims at GNU compatibility, with GNU differences classified as bugs. If your constraint is a few megabytes of flash, BusyBox is the right answer. If your constraint is a script written against GNU that has to run on Windows, uutils is the closer match.
The other alternative is simply GNU coreutils itself, which remains the reference implementation and the thing uutils measures against. On Linux it is already installed, it is what your distribution tests, and it has decades of edge cases baked in. Choosing uutils means choosing a reimplementation of that reference on the strength of portability, not on the strength of new behaviour. That is a defensible trade only if portability is something you actually need.
Licence, release cadence and the cost of tracking upstream
uutils/coreutils is MIT licensed, which is permissive and imposes no copyleft obligation on the rest of your stack. The README points to a separate LICENSE file in the repository for the full text. Note that the project bundles or links optional third-party components depending on the features you enable, notably OpenSSL for the `openssl` feature and libselinux for `feat_selinux`. Those carry their own licences, and enabling the features pulls them in. This is a description of what the repository states, not legal advice; if you redistribute a binary, check the licence of every feature you turned on.
Upgrade cost is the part people underestimate. The project releases frequently, with 0.12.0 on 2026-09-17, 0.11.0 on 2026-08-31 and 0.10.0 on 2026-08-05, and the last push to the main branch was on 2026-09-20. The README advises bug reporters to use the binary from the latest commit rather than a stable tag, which tells you the stable tags lag the fixes. If you pin to a tag for reproducibility, you are also pinning to whatever compatibility gaps existed at that tag. Budget for periodic rebuilds and for re-running your own comparison tests after each one.
The distribution angle changes the calculus. Ubuntu has shipped uutils coreutils by default since version 25.10, so on that release you are already running it whether or not you chose to. If you are on Ubuntu 25.10 or later, the question is not whether to adopt it but whether your scripts still behave as expected under it.
Editorial conclusion
Adopt uutils/coreutils if you need the same utilities on Windows, macOS, Linux or WASI, or if you are packaging for a distribution that already ships it, as Ubuntu has since 25.10. Do not adopt it if your scripts depend on exact GNU output and you have not diffed the two. Verify first by building the same feature set you intend to ship and running your own test suite against both binaries.
Frequently asked questions
What are the differences between uutils and coreutils?
uutils/coreutils is a Rust reimplementation of GNU coreutils, and the README states that differences with GNU are treated as bugs, with the goal of matching stdout and exit codes exactly. The README also states that some options might be missing or that different behaviour might be experienced. One documented deliberate divergence is that parse errors at a terminal are shown as a compiler-style report with a caret, while scripts and pipes still receive the plain GNU message.
How do I install uutils/coreutils on Windows?
The README documents building from source with Cargo, using a platform feature such as cargo build --release --features windows. It also notes that prebuilt binaries, manpages and shell completions are published from the main branch, and that a latest stable tag exists for reproducible packaging. The README does not give a Windows package manager command.
How do I install uutils/coreutils on macOS?
The README's documented path is to clone the repository and run cargo build --release, which produces the multicall binary named coreutils. Platform-specific utilities are added with a feature flag, for example --features unix. The README does not list a Homebrew formula for the project.
How do I build only some of the uutils/coreutils utilities?
The README shows combining --features with --no-default-features, for example cargo build --features "base32 cat echo rm" --no-default-features. With GNU Make, the equivalent is make SKIP_UTILS='UTILITY_1 UTILITY_2' to leave utilities out. Individual binaries can also be built per package, for example cargo build -p uu_base32 -p uu_cat -p uu_echo -p uu_rm.
What is the difference between BusyBox and uutils/coreutils?
Both ship a multicall binary, but they aim at different targets. BusyBox is built for small and embedded systems with a reduced set of utilities. uutils/coreutils aims to be a drop-in replacement for GNU coreutils across Linux, macOS, BSD, Windows and WASI, and the README states that differences from GNU are treated as bugs.
Why would I enable the openssl feature when building uutils/coreutils?
The README states the feature routes the checksum utilities such as md5sum and sha256sum through OpenSSL's libcrypto instead of the pure-Rust digest crates, and that the speedup is largest on CPUs without SHA-NI hardware acceleration. By default OpenSSL is built from source and statically linked, and setting OPENSSL_NO_VENDOR=1 at build time links against the system libcrypto dynamically instead.
Official sources
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)