A verdict first
One line tells you whether to look closer. The details sit underneath for when you do.
npryx is a drop-in for npx. It checks install scripts, provenance, publish age, downloads and lookalike names, leads with a one-line verdict, then runs exactly the version it showed you.
$ npryx esbuild npryx: about to fetch & run a package from the npm registry ! esbuild@0.28.1: 2 warnings, review before running - runs install scripts (postinstall) which execute code on install - published only 11d ago, brand new with little scrutiny yet package esbuild@0.28.1 (asked: latest) published 11d ago weekly dl 41,284,663 maintainers esbuild repo git+https://github.com/evanw/esbuild.git integrity sha512-HrJrvZv5ayxBzPfwp… provenance ✓ https://slsa.dev/provenance/v1 install hook ! yes, runs code on install [y] run [s] run with --ignore-scripts (safer) [a] always-trust this version [N] abort (default):
$ npryx esbuild npryx: ✓ esbuild@0.28.1 is trusted (approved 2026-10-02) Same version, same integrity: the bytes you approved run with no prompt. If esbuild@0.28.1 ever comes back with different bytes, npryx stops: ✗ do not run esbuild@0.28.1: it is not the bytes you approved
$ npryx cowsay moo < /dev/null npryx: ! refusing to auto-run in a non-interactive shell (fail-closed). Set NPRYX_ALLOW=<name>[@<version>] or NPRYX_YES=1 to override. $ echo $? 1 # allow by name, by version, or exactly these bytes $ NPRYX_ALLOW='cowsay@1.6.0#sha512-…' npryx cowsay moo
$ npryx --json cowsay moo { "schemaVersion": 1, "decision": "needs-approval", "reason": "untrusted", "message": "not trusted yet: a human should review the packages, then approve them", "command": { "npryx": ["cowsay@1.6.0", "moo"], … }, "approve": "cowsay@1.6.0#sha512-…", "packages": [ … ] } $ echo $? 3
npx fetches and runs code in one step. npryx puts a decision in between, and makes sure the thing you decided on is the thing that runs.
One line tells you whether to look closer. The details sit underneath for when you do.
The version in the preview is the version that runs. npryx never resolves the name again between showing and running.
Press a to trust a version. If that version ever comes back with different bytes, npryx stops: npm never allows that, so something was tampered with.
Use it where you would have typed npx. Nothing runs until you have seen the package and said yes.
Same arguments as npx.
From the npm registry, on your machine.
Abort is the default.
Exactly the version you saw.
From npm, published with provenance, or from Homebrew.
$ npm install -g npryx$ brew install jeecabs/tap/npryxYou get the preview, then choose: run, run with --ignore-scripts, always trust this version, or abort.
$ npryx cowsay mooAn optional alias sends npx through npryx. It shows the change and asks first; npryx --remove-alias takes it out.
$ npryx --setup-aliasEverything comes from the npm registry and runs on your machine. Nothing is sent anywhere else unless you turn on remote scanning.
Whether preinstall, install or postinstall hooks will execute code the moment the package lands. Choose s to run it with --ignore-scripts instead.
Whether the version carries a signed build attestation linking it to its source.
Brand new versions and little-used packages stand out before they run.
Names one edit away from a popular package, the usual shape of a typosquat.
Whether the maintainers have deprecated the version, and what they said.
The sha512 of the exact tarball. Trust, NPRYX_ALLOW tokens and JSON approvals are all tied to these bytes.
Without a person at the terminal there is nobody to read a preview, so npryx refuses by default and tells you how to allow exactly what you meant.
In a non-interactive shell, any package you have not trusted is refused with exit code 1. Allow by name, by name@version, or by an exact-bytes token. NPRYX_YES=1 opts out entirely. Tampered bytes are refused whatever you set.
# .github/workflows/ci.yml
env:
NPRYX_ALLOW: "prettier,cowsay@1.6.0"
npryx --json <pkg> prints one JSON document and never runs anything. The approval token covers the previewed bytes and nothing else.
| allow | exit 0 | Trusted, local, or allowed. Safe to hand to npryx to run. |
| needs-approval | exit 3 | Verified but not trusted. Show a human, then pass the approve token. |
| refuse | exit 1 | Tampered, a confirmed threat, or unverifiable. Do not run it. |
The registry tells you what a package is. A scan reads what its code does. It is optional, off until you turn it on, and the scanner is open source.
The scan service reads the package's code, compares it with the previous version, and checks OSV for known-malware advisories. It flags code that would send tokens, environment variables or credentials off your machine:
Only packages from the public npm registry are sent. Private package names never leave your machine.
The CLI is free and does everything locally. Pay only if you want us to run the scanner for you.
The full CLI, and the scanner if you host it yourself.
$ npm install -g npryxHosted remote scanning, nothing to run yourself.
Anything else is in the README.
No. npryx runs npx for you, pinned to the version it showed you, after you have seen what that version does. npx stays installed and works as before. If you want every npx to go through npryx, run npryx --setup-alias; it asks before it changes your shell config, and nothing is aliased unless you opt in.
It fails closed. In a non-interactive shell npryx refuses, with exit code 1, any package you have not already trusted. Allow packages with NPRYX_ALLOW: a name, name@version, or an exact-bytes token (name@version#sha512-…). NPRYX_YES=1 opts out entirely. Tampered bytes are never run, whatever you set.
npryx --json <pkg> checks a command without running it and prints one JSON document with a decision: allow (exit 0), needs-approval (exit 3) or refuse (exit 1). For needs-approval it includes an approve token for exactly the previewed bytes, so a human can approve that version and nothing else.
Nothing, unless you turn remote scanning on. When it is on, npryx sends the name, version and integrity of packages from the public npm registry. Packages that are not on the public registry are never sent, so private package names never leave your machine. If the service is down, slow or its signature does not verify, npryx behaves exactly as it does without it.
Yes, for free. The scan service is open source (Rust) and lives in the npryx repository under scan-service. Point npryx at your own instance with npryx --scan-config <url>. Pro is the same scanner, hosted for you.
That the scan found nothing it looks for: no known-malware advisory, and no code that sends tokens, environment variables or credentials off the machine. It does not mean the package is safe. That is also why a scan result can only add caution: a clean result never clears a warning npryx shows you locally.
Node 22 or newer. It has zero runtime dependencies, is open source under the ISC license, and is published to npm with provenance, so you can check it the same way it checks everything else.
Install npryx, and use it the next time you reach for npx.
$ npm install -g npryx