npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fossity/probe-cli

v0.1.4

Published

Captures fingerprints and dependency data from your code, without shipping your code.

Readme

Probe CLI

A command-line and terminal-UI code auditing probe. It fingerprints a codebase, reads its declared dependencies from manifests and lockfiles, counts files, optionally obfuscates paths, and writes a single encrypted package for an auditor.

It succeeds the Fossity Probe desktop application, which is discontinued.

Your source code never leaves the machine: the package contains winnowing fingerprints, package URLs and counts, not file contents.

$ probe-cli scan .
  ✔ Indexing files (1/1)
  ✔ Fingerprinting source (1/5)
  ✔ Analyzing dependencies (2/5)
  ✔ Counting files (3/5)
  ✔ Obfuscating paths (4/5)
  ✔ Attaching files (5/5)

Scan complete
  files seen           1284
  fingerprinted        902
  filtered out         382
  dependency files     11 (1043 purls)
  from lockfiles       806 purls  npm:612  pypi:98  cargo:96

  → /home/you/acme-app.fossity (612.4 KB)

Install

Pick whichever is easiest — none of them needs a checkout.

Standalone binary (no Node required)

# Linux / macOS
curl -fsSL https://raw.githubusercontent.com/fossity/probe-cli/main/install.sh | sh

# Windows (PowerShell)
irm https://raw.githubusercontent.com/fossity/probe-cli/main/install.ps1 | iex

Already have Node 18+?

npx fossity@latest scan .            # runs without installing anything
npm install -g @fossity/probe-cli    # or install it permanently

fossity publishes the same build as @fossity/probe-cli, under a shorter name.

npx resolves the newest version from the registry on each run, so the bare form is current too; @latest only makes that explicit. Two cases do reuse an older copy: asking for one by version (npx [email protected] keeps using 0.1.0, as it should), and running offline, where npx falls back to its cache. rm -rf ~/.npm/_npx clears it if you ever need to.

An installed copy is different: neither the binary nor a global npm install updates itself. Check with probe-cli --version against the latest release, and re-run the install command to update.

Or download a binary directly from the releases page — one file per platform, gunzip and run. Verify it against the published SHA256SUMS.

Unsigned binaries

The binaries carry no Developer ID or Authenticode certificate. What that means in practice:

  • The install scripts above are unaffected. macOS attaches its quarantine flag in the browser, not in curl, and Windows marks downloads the same way, so neither one-liner triggers a warning.
  • Downloading from the releases page in a browser does trigger one. On macOS, right-click the file and choose Open, or run xattr -d com.apple.quarantine <file>. On Windows, choose More info then Run anyway.
  • npx is unaffected — no operating-system gatekeeping applies to it at all.

Check the published SHA256SUMS if you want to verify what you downloaded; it is a stronger check than a code signature, since it is produced by the same public build that produced the binary.

Use

Run it with no arguments for the guided flow: project information, obfuscation, then a summary to confirm before anything is written.

probe-cli

Or drive it non-interactively, which is what you want in CI:

probe-cli scan . --email [email protected] --license MIT -o audit.fossity

Commands

| Command | What it does | | ------------------------- | ---------------------------------------------------------- | | probe-cli | guided terminal wizard | | probe-cli scan [folder] | fingerprint a folder and write the package | | probe-cli deps [folder] | list the dependencies found, write nothing | | probe-cli formats | list every manifest/lockfile format this build understands | | probe-cli workspace | print the working directory used for intermediate files |

Useful flags

| Flag | Effect | | ---------------------- | ------------------------------------------------------------------------------------ | | -e, --email <email> | contact email — the auditor requires it | | -o, --output <file> | where the package goes | | -l, --license <spdx> | default license of your own code | | --obfuscate <words> | comma-separated words to strip from every path in the package | | --sbom <file> | attach a known-components SBOM | | --raw | write a plain .zip instead of an encrypted package, to review what you are sending | | --json | machine-readable result, for CI | | --verbose | mirror the scan log to stderr |

Reviewing what you send

Every scan leaves the package contents in the clear next to the package itself:

audit.fossity              the encrypted package, for the auditor
audit.fossity.contents/    the same files, readable

The package is encrypted to the auditor's public key, so you cannot open it after it is written. That directory is how you check what leaves your machine — it is byte for byte what the package contains, and a test enforces that. Read dependencies.json and winnowing.wfp before you send anything.

Fingerprints cannot be reversed to the code: they are winnowing hashes, from which the source cannot be reconstructed.

Paths inside the package always use forward slashes, whichever platform produced it, so a scan of the same tree yields the same record on Windows, macOS and Linux.

What the package contains

| File | Contents | | ---------------------- | --------------------------------------------- | | winnowing.wfp | winnowing fingerprints (hashes, never source) | | dependencies.json | package URLs from manifests and lockfiles | | file_count.csv | file counts by extension | | projectMetadata.json | the contact details and license you supplied |

Dependency coverage

Dependency discovery runs two parsing engines. The scanoss SDK covers package.json, package-lock.json, yarn.lock, pom.xml, build.gradle, requirements.txt, pyproject.toml, Gemfile, Gemfile.lock, go.mod, go.sum, *.csproj and packages.config. This program adds the lockfile formats it does not:

| Ecosystem | Added formats | | ------------------ | -------------------------------------------------------------------------------- | | npm | pnpm-lock.yaml, npm-shrinkwrap.json, bun.lock | | Python | poetry.lock, Pipfile, Pipfile.lock, requirements*.txt, environment.yml | | Rust / C++ | Cargo.lock, Cargo.toml, conan.lock, vcpkg.json | | PHP | composer.json, composer.lock | | JVM | gradle.lockfile | | .NET | packages.lock.json, paket.lock, *.fsproj, *.vbproj | | Apple | Podfile.lock, Package.resolved, Cartfile.resolved | | Dart / Elixir / Go | pubspec.yaml, pubspec.lock, mix.lock, Gopkg.lock |

Detection is not configurable: every scan runs both engines over every file, vendored directories included, because a checked-in node_modules is part of what ships. There is no flag to narrow it.

probe-cli formats prints the live list. Two deliberate behaviours:

  • Local packages are not reported. workspace:*, file:, link:, path and git specifiers name things that exist in no registry, so no purl is emitted for them.
  • Ranges stay ranges. A manifest constraint like ^4.18.2 goes in requirement; the purl only carries a version when the file actually pins one. Lockfiles pin, so their purls carry versions.

bun.lockb is binary: it is detected and reported as a gap rather than silently ignored.

Privacy

Lockfiles routinely name internal packages and private registry hosts, so any URL-shaped field is dropped from the dependency records before they are written, and package names go through the obfuscation dictionary when one is in use.

The obfuscation dictionary (obfuscationMapper.json) is written to the working directory and is not included in the package — it is the key that maps obfuscated paths back to real ones, and it stays with you. Keep it if you need to interpret the auditor's findings; pass --keep-workspace to retain it.

Rebranding

Everything brand-specific lives in brand.config.json. npm run brand:check fails the build if a vendor name is hardcoded anywhere in src/ or scripts/ — attribution notices excepted, since the GPL requires those — so the list below is the whole job.

  1. Fork and edit brand.config.json:

    {
      "productName": "Acme Audit Probe",
      "binaryName": "acme-probe",
      "shortName": "Acme Probe",
      "vendor": "Acme",
      "tagline": "Captures fingerprints from your code, without shipping your code.",
    
      "packageExtension": ".acme",
      "versionFooterTag": "ACME_VERSION",
      "obfuscationKeyPrefix": "ACME",
      "workspaceDirName": "acme-workspace",
      "configDirName": "acme-probe",
    
      "websiteUrl": "https://acme.example",
      "uploadUrl": "https://acme.example/upload",
      "supportEmail": "[email protected]",
      "issuesUrl": "https://github.com/acme/probe-cli/issues",
    
      "publicKeyPem": "-----BEGIN PUBLIC KEY-----\n…your key…\n-----END PUBLIC KEY-----\n",
      "accentColor": "magenta"
    }

    publicKeyPem is the RSA public key your back end holds the private half of. Everything else is cosmetic except the three format fields called out below.

  2. Apply and verify:

    npm run brand:apply    # updates package.json name/bin/homepage and the install scripts
    npm run brand:check    # fails if any brand string is hardcoded in the source
    npm test
    npm run build:binary
  3. Point the installers at your repository. Set "repository": "acme/probe-cli" in brand.config.json and re-run npm run brand:apply, which rewrites the defaults in install.sh and install.ps1. Update .github/workflows/release.yml and the artwork by hand.

Three fields are wire format, not decoration

packageExtension, versionFooterTag and publicKeyPem are read by whatever ingests the package. Change them only together with the receiving end:

  • publicKeyPem — the package body is AES-128-CBC, its key and IV sealed with this RSA key. The wrong key makes the package undecryptable.
  • versionFooterTag — the last 100 bytes of the file are <TAG>:<version> padded with NULs. An ingest that greps for the old tag will reject the file.
  • packageExtension — upload forms usually filter on it.

Keep the originals if you are talking to an existing back end, and rebrand only the surface.

Try a rebrand without rebuilding

PROBE_BRAND_CONFIG points the binary at a different brand file at runtime — useful for testing before you commit to a fork:

PROBE_BRAND_CONFIG=/tmp/acme-brand.json probe-cli scan . --email [email protected]

Development

npm install

npm run dev -- scan ./some-folder --email [email protected]   # run from source
npm test                # 110 tests: parsers, pipeline, package format, CLI, end to end
npm run typecheck
npm run verify          # brand check, types, formatting and tests, as CI runs them
npm run build           # dist/probe.cjs, a single file of about 4.8 MB
npm run build:binary    # bin/probe-<version>-<os>-<arch>, 99 MB (33 MB compressed)

Layout, data flow and the reasoning behind the design are in ARCHITECTURE.md.

src/core holds the scanning pipeline and is free of any terminal or CLI concern, so it can be driven as a library; src/cli is the only place that reads arguments or writes to the terminal.

Adding a lockfile format takes one entry in LOCKFILE_DEFINITIONS and one parser function; see the same-named section of ARCHITECTURE.md.

Licensing

Copyright (C) 2021-2026 Fossity LLC (https://fossity.com).

This program is free software licensed under the GNU General Public License, version 2 only (SPDX-License-Identifier: GPL-2.0-only). The full text is in LICENSE.

Parts of src/core derive, in modified form, from the discontinued Fossity Probe desktop application, which was itself based on the SCANOSS Audit Workbench. Both are GPL-2.0. NOTICE records which parts are derived and which were written for this program; every source file carries an SPDX header, and .reuse/dep5 covers the files that cannot.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

What this means if you fork it

  • A rebranded fork is still a derivative work: it must remain GPL-2.0, keep the copyright notices and the LICENSE file, and offer source to anyone it distributes binaries to.
  • Rebranding changes the name, not the licence. Replacing the vendor name everywhere is expected and supported (see Rebranding); removing the attribution is not permitted.
  • Contributions are accepted under the same licence.

Third-party components

Dependencies keep their own licences; package.json lists them and npm ls resolves the tree. The notable one is scanoss (MIT), which provides the winnowing fingerprint engine and the package manifest parsers this program builds on. A standalone binary embeds the Node runtime, which is MIT licensed.