cargo-npm: Distribute Rust CLIs via npm without postinstall scripts
I recently built `cargo-npm`, a tool that packages and distributes Rust binaries directly to the npm registry.
## Why another distribution tool?
While tools like `cargo-dist` are excellent for general release engineering, their npm installers typically rely on `postinstall` scripts to download pre-compiled binaries from external sources like GitHub Releases at install time. I wanted a solution that works natively within the npm ecosystem without requiring lifecycle scripts.
Relying on npm's dependency graph rather than `postinstall` scripts provides several architectural advantages:
* It respects `--ignore-scripts`, which is increasingly enforced in corporate and CI environments for security reasons (it's also the default on pnpm). * It prevents installation failures caused by strict firewalls or proxies blocking GitHub Releases downloads. * It utilizes npm's native caching mechanisms, speeding up repeated installations.
## How it works
Instead of fetching binaries at runtime, `cargo-npm` takes your compiled targets and generates individual, platform-specific npm packages (e.g., `my-tool-linux-x64`). Each of these packages contains the actual binary and uses `os`, `cpu` and `libc` constraints in its `package.json`.
It then generates a main package that users install. This main package lists the platform packages as `optionalDependencies`. When a user runs `npm install my-tool`, npm's native resolution ensures it only downloads the binary that matches the host system. A lightweight Node.js shim in the main package resolves the matching binary and executes it.
## Usage
You cross-compile your Rust crate for your desired targets, and then run `cargo npm generate` followed by `cargo npm publish`. The tool handles the package generation, metadata forwarding, and parallel publishing.