Subscribe to all “engineering” posts via RSS or follow GitHub Changelog on Twitter to stay updated on everything we ship.

~ cd github-changelog
~/github-changelog|main git log main
showing all changes successfully

npm query is a new top-level command as of npm v8.16.0 which accepts a Dependency Selector (as defined in the Dependency Selector Syntax Specification) & returns a filtered JSON Array/NodeList of dependencies from your project. We believe this capability has been a missing piece of the package management ecosystem; With its introduction we hope to unlock the potential for developers to self-serve in asking new, complex questions about their dependencies, their relationships & associative metadata.

For many JavaScript developers, the Dependency Selector Syntax will look very familiar as it is actually an adapted form of CSS. We leveraged this existing, known language & its operators to make disparate package information broadly accessible.

Example Uses:

If I wanted to list all of my dependencies (similar to npm list --all) I can run:

npm query "*"

If I wanted to find every version of react & lodash in my project I can run:

npm query "#react, #lodash"

If I wanted to find all react versions not-defined as a peer dependency I can run:

npm query "#react:not(.peer)"

If I wanted to find all the dependencies in my project that used an MIT license I'd change that query to be:

npm query "[license=MIT]"

If I wanted to find all the git dependencies in my project I can run:

npm query ":type(git)"

If I wanted to find out which of my transitive dependencies used a postinstall script I could run:

npm query ":attr(scripts, [postinstall]):not(:root > *)"

Programmatic Usage

We know many developers in the ecosystem will also want to leverage this new syntax themselves, so we've built it right into the programmatic brain of the CLI. Under the hood, we’ve added a new .querySelectorAll() method to the existing Node Class we use in the @npmcli/arborist library. Tooling authors can now load up & query their dependencies just like we do.

// index.js
const Arborist = require('@npmcli/arborist')
const arb = new Arborist({})

arb.loadActual((tree) => {
  // query all workspaces
  const results = await tree.querySelectorAll('.workspace')

You can learn more about the syntax & usage in our documentation here:

What's next?

Looking ahead we’ve got work planned to add new pseudo states & selectors based on registry metadata that should unlock another host of capabilities aimed at auditing (examples include: :outdated :deprecated :vulnerable :cve() & :cwe()). As documented in the original RFC proposal we will also consider supporting a query flag or reading from stdin to existing commands.

See more