Unix utilities, in one Rust binary.
A BusyBox-style multi-call binary in Rust — 78 Unix utilities, one ~2 MB executable, native on Linux, Windows, and macOS. Functional port of Real-Fruit-Snacks/mainsail with verified parity.
$ jib seq 100 | jib sort -rn | jib head -3 100 99 98 $ jib find . -name '*.rs' -size +1k -mtime -7 ./src/applets/sed.rs ./src/applets/awk.rs ./src/applets/jq.rs $ jib tar -czf src.tgz src/ $ jib sha256sum src.tgz d4f2a8b1c3e7… *src.tgz
A familiar POSIX surface. Real flag coverage, not stubs. Same behavior on Windows, macOS, and Linux — and the same bytes the Python original produces.
Every common shell tool dispatched through a single executable — POSIX coreutils plus jq, http, dig, nc, archives, hashing, and the BusyBox parity gap-fillers. Symlink it as cat, ls, grep and the multi-call dispatcher takes over.
Runs on bare Windows — no WSL, no Cygwin, no git-bash. Recognizes dir, type, copy, del, where as native aliases.
find with -exec, -prune, parens, boolean ops. sed with addresses and in-place edit. awk with BEGIN/END, patterns, arrays, gsub. jq with pipes, select, map, 20+ built-ins.
Binary-safe through cat/tee/gzip. tail -f with rotation detection. xargs -0 for paths with backslashes.
The tests/parity harness runs both this binary and the Python original against the same fixtures and asserts byte-for-byte equality of stdout and exit codes. Behavior drift gets caught the next time CI runs — no manual cross-checking.
One Rust file per applet — most are 100–300 lines. Add a new one by dropping a module under src/applets/ exposing pub const APPLET: Applet and an entry in the registry's ALL slice.
Pick exactly the surface you ship. --features slim drops engines and archives down to 34 POSIX coreutils — a 545 KB binary. Or compose "slim,hashing,archives" à la carte.
Linux × x86_64 / ARM64 (glibc), Windows × x86_64 / ARM64, macOS ARM64, plus a separate musl-linked Linux x64 binary — runs on Alpine, distroless containers, and any musl-libc Linux.
Each applet implements common POSIX flags. Run jib <applet> --help for per-applet usage. The ● markers flag known parity gaps tracked in PARITY.md.
Same shape as the Python original — clean separation between entry point, dispatch logic, applet registry, and per-applet implementations. Adding an applet means dropping one file.
main.rs collects env::args and hands them to cli::run. The exit code is clamped to a u8 ExitCode.
cli.rs resolves the applet from argv[0]'s lowercased stem (multi-call) or argv[1] (subcommand). Intercepts --help only — -h stays free for applet flags like df -h.
registry.rs builds a BTreeMap<&str, &'static Applet> once via OnceLock, indexing every canonical name and alias.
78 modules in src/applets/, ranging from ~10 lines (true) to ~1100 (awk). Read bytes via io::stdin().lock(); write via io::stdout().lock(). Return 0 / 1 / 2 (success / runtime / usage).
Pre-built binaries on the releases page. Build from source for the slim feature set or to add applets.
# From a release $ curl -LO https://github.com/Real-Fruit-Snacks/jib/\ releases/latest/download/jib-linux-x64 $ chmod +x jib-linux-x64 $ ./jib-linux-x64 --version jib 0.1.0 # From source — Rust 1.75+ $ git clone https://github.com/Real-Fruit-Snacks/jib.git $ cd jib && cargo build --release → target/release/jib (~2 MB) # Slim build — POSIX coreutils only, no engines/archives $ cargo build --release \ --no-default-features --features slim → 545 KB, 34 applets # Custom à la carte $ cargo build --release \ --no-default-features --features "slim,hashing"
# Daily pipelines (find + awk + jq, all in one binary) $ jib find . -name '*.rs' -mtime -7 $ jib awk -F, '{s+=$3} END{print s/NR}' data.csv # jq subset $ jib jq '.servers[] | select(.region) | .name' inv.json # DNS without dig installed $ jib dig MX gmail.com +short # Cross-platform integrity $ echo -n abc | jib sha256sum ba7816bf8f01cfea414140de5dae2223… # Verify parity against the Python original $ python tests/parity/run.py 76/76 matched (0 skipped)