lpm query
CSS-like selector queries against installed packages and behavioral tags.
lpm query <selector> [flags]Selector engine that targets behavioral tags, package state, and dependency relationships across the installed set. Pairs with lpm audit — audit is the broad report; query is the precision tool.
Use it in CI to gate on specific risky combinations, in shells to grep through installed packages by behavior, or in agents to ask structured questions about the dep tree.
Examples
lpm query :eval # any package that uses eval()
lpm query :network # any package making outbound HTTP
lpm query :scripts:not(:built) # has lifecycle scripts but they haven't run
lpm query ":root > :network" # direct deps that hit the network
lpm query "#lodash" # find lodash in the tree
lpm query :critical --assert-none # CI gate: fail if any critical-tagged pkg
lpm query --count # tag counts across all packages
lpm query :eval --format mermaid > eval-graph.mmd # subgraph diagramSelectors
Each selector matches packages by behavioral tag, state, or identity. Tags are computed by the same static analysis pipeline that backs lpm audit.
Behavioral tags
| Tag | Matches packages that |
|---|---|
:eval | Use eval, Function(), or vm.runInThisContext |
:network | Make outbound HTTP / WS connections |
:fs | Touch the filesystem outside their own directory |
:shell | Spawn shells (spawn, exec, execSync) |
:child-process | Use child_process (any form) |
:native | Ship native modules (.node, .wasm) |
:crypto | Use cryptographic primitives |
:dynamic-require | Use dynamic require() (variable arg) |
:env | Read process.env |
:ws | Use WebSockets |
:obfuscated | Show signs of code obfuscation |
:high-entropy | Contain high-entropy string blobs |
:minified | Ship minified-only source |
:telemetry | Make telemetry / analytics calls |
:url-strings | Contain URL string literals |
:trivial | Tiny — measured by AST node count |
:protestware | Match a curated list of known protest-license / sabotage packages |
Dependency state
| Tag | Matches |
|---|---|
:git-dep | Installed from a git URL |
:http-dep | Installed from an HTTP tarball URL |
:wildcard-dep | Declared with * or latest |
:copyleft | Copyleft license (GPL family) |
:no-license | No license field |
:scripts | Declares lifecycle scripts (preinstall/postinstall/etc.) |
:built | Lifecycle scripts have been run (the package is in the trust set + executed) |
:vulnerable | Listed in OSV / registry advisories |
:deprecated | Marked deprecated by the publisher |
Origin
| Tag | Matches |
|---|---|
:lpm | @lpm.dev/* packages |
:npm | npm packages |
Severity
Severity selectors are aliases — each one expands to an OR of the underlying behavioral tags assigned to that level. Useful for "fail on any critical" gates without enumerating the tags by hand.
| Tag | Expands to |
|---|---|
:critical | :obfuscated OR :protestware OR :high-entropy |
:high | :eval OR :child-process OR :shell OR :dynamic-require OR :scripts OR :vulnerable |
:medium | :network OR :git-dep OR :http-dep OR :wildcard-dep OR :no-license OR :native |
:info | :fs OR :crypto OR :env OR :ws OR :telemetry OR :trivial OR :copyleft OR :minified OR :url-strings |
Structural
| Tag | Matches |
|---|---|
:root | The invocation root — the package.json closest to where the command ran |
:workspace-root | The workspace container in a monorepo (same as :root outside monorepos, distinct when invoked from a workspace member) |
Combinators
| Combinator | Meaning |
|---|---|
:a:b | AND — package matches both tags |
:a, :b | OR — package matches either tag |
:not(:a) | NOT — package doesn't match :a |
#name | Identity — match a specific package by name |
:root > :child | Direct-dep — :child is a direct dependency of :root |
CI gating
lpm query :critical --assert-noneExits non-zero if any package matches the selector. Use to fail the build on specific risky combinations:
# fail on a vulnerable package that hasn't been patched
lpm query ":vulnerable:not(:built)" --assert-none
# fail on a transitively-pulled package that uses eval AND has lifecycle scripts
lpm query ":eval:scripts" --assert-none--assert-none is the canonical CI-gate flag. For broader gating with severity policies, lpm audit --fail-on is usually a better fit.
Counts and details
lpm query --countTabulates tag counts across every installed package, grouped by severity. Useful for high-level "how risky is my tree right now" surveys.
lpm query :network --query-verboseHuman list output includes a second tags: line for each matched package that carries behavioral tags. --query-verbose keeps the same human shape and includes the full analysis fields in JSON output.
Output formats
lpm query :eval --format list # default — names, one per line
lpm query :eval --format mermaid # Mermaid subgraph diagram| Format | Output |
|---|---|
list (default) | Package names plus an indented tags: detail line when tags are present |
mermaid | Mermaid graph block showing the matched packages as a dependency subgraph |
For broader graph rendering (full tree, DOT, JSON, HTML), use lpm graph.
Flags
| Flag | Effect |
|---|---|
<selector> | Optional selector expression. Required unless --count. |
--count | Show tag counts across all packages, grouped by severity |
--query-verbose | Include full per-match analysis details in JSON output |
--assert-none | Exit non-zero if any package matches (CI gate) |
--format <list|mermaid> | Output format (default list) |
Plus the global flags. --json emits an array of matched packages with name, version, optional path, and (under --query-verbose) analysis, hasScripts, isBuilt, isVulnerable.
See also
lpm audit— broader report with vulnerability + behavior datalpm graph— render the full dep tree- Security audit — design overview of the tag system