LPM CLI

lpm graph

Inspect resolved dependencies, explain why a package is present, and export dependency diagrams.

Inspect the dependency graph in lpm.lock, or trace the packages that require a dependency.

lpm graph [OPTIONS] [PACKAGE]
lpm ls [OPTIONS] [PACKAGE]
lpm why [OPTIONS] <PACKAGE>

Quickstart

lpm graph --depth 2
lpm why lodash
lpm graph --json
ModeEffect
lpm graphShow the selected project's dependency tree.
lpm graph <package>Show one package and its dependency subtree.
lpm graph --why <name>Show every path to dependencies with this name.
lpm lsAlias for lpm graph, with the same arguments and flags.
lpm why <name>Shortcut for lpm graph --why <name>. Supports shared global flags.

Graph uses local project files. It requires a usable lpm.lock, but it does not require installed packages or contact a registry.

LPM CLI supports npm, private registries, and the LPM.dev Registry. Graph can include packages from each source.

Examples

# Inspect an exact resolved version
lpm graph react@19.0.0

# Show production roots and their dependencies
lpm graph --prod --depth 3

# Keep matching package subtrees and the paths to them
lpm graph --filter react

# Export a diagram
lpm graph --format mermaid > dependencies.mmd
lpm graph --format dot | dot -Tpng > dependencies.png

# Write an interactive HTML graph without opening a browser
lpm graph --format html --no-open

# Save a machine-readable explanation
lpm why lodash --json > why-lodash.json

For a reusable report, define an uncached task:

lpm.json
{
  "tasks": {
    "deps:graph": {
      "command": "lpm graph --prod --format html --no-open",
      "cache": false
    }
  }
}
lpm run deps:graph

There is no dedicated graph configuration in lpm.json. The task's command holds the graph options. cache: false regenerates the report each time.

For a different one-run view, run the graph command directly. An explicit lpm.json task command takes precedence in lpm run.

Project and workspace scope

Graph finds the nearest project manifest and its applicable lpm.lock. Invocation from a nested source directory uses the same project.

In a workspace member, graph uses that member's dependency tree. Sibling-only dependencies do not appear. Run the command from the workspace root to inspect its root dependencies.

The manifest supplies the project identity and direct dependency names. The lockfile supplies resolved packages, dependency edges, and resolved peer edges.

If the manifest changed after the last install, update the lockfile with lpm install before you inspect the graph.

Select a package

lpm graph react
lpm graph react@19.0.0

A name selects the nearest matching package. If multiple packages have the same depth, the first sorted identity wins.

A name and version select that exact coordinate. Separate dependency instances can share both values. If the coordinate is ambiguous, the error lists exact keys.

Copy one of those keys, including any suffix:

lpm graph '<name>@<version>#<instance-id>'

The selected dependency becomes the graph root. It still counts as a package, and its direct children start at level 2.

lpm why <package>

lpm why lodash
lpm graph --why lodash --format json

Why accepts a package name and includes all its resolved versions. It shows every path from the selected graph root to that dependency.

Recorded overrides and patches appear with the explanation. These records describe the last installation that wrote them.

If the name is absent, the command succeeds with a not-found result. Use lpm query with --assert-none for a presence gate.

Why supports human output and JSON. Other --format values are incompatible with --why.

Dense graphs can produce large reports because the number of paths can grow exponentially.

Filter the graph

lpm graph --depth 2
lpm graph --filter press
lpm graph --prod
lpm graph --dev
FilterEffect
--depth <N>Keep nodes within N shortest-path levels. The current graph root is level 1.
--filter <NAME>Keep matching dependency subtrees and every path that connects them to the root.
--prodSelect production and optional direct dependencies, then keep their reachable dependencies.
--devSelect development direct dependencies, then keep their reachable dependencies.

The name filter uses a case-sensitive substring. For example, press matches express. The project name does not count as a dependency match.

--prod and --dev cannot be combined. A shared transitive package remains if a selected root requires it.

Depth uses the shortest path to each node. A shared node can appear through a longer retained path, so tree indentation can exceed the depth limit.

All formats use the same filtered graph. With a package argument, depth starts at that package. An empty selection still produces a valid output document.

Output formats

FormatDestinationUse
tree (default)Standard outputInspect the tree in a terminal.
dotStandard outputCreate a Graphviz diagram.
mermaidStandard outputInclude a diagram in Markdown.
jsonStandard outputRead graph data from a script or tool.
statsStandard outputInspect counts, depth, and duplicate versions.
html<project>/.lpm/graph.htmlExplore an interactive graph in a browser.

In HTML, collapse a package to hide its dependency branches. A shared dependency stays visible through another expanded parent.

HTML opens the file in the default browser. With --no-open, it only writes the file. The destination belongs to the selected project, including a workspace member.

All other formats print to standard output. Use shell redirection to save them.

JSON

lpm graph --json
lpm graph --format json
lpm why lodash --json

Global --json selects JSON output. It cannot accompany --format dot, mermaid, stats, or html.

Graph JSON contains success, root, package counts, max_depth, duplicates, nodes, and edges.

The synthetic project root does not count as a package. A selected dependency root does count. Separate instances remain separate nodes.

Why JSON contains target, found, path_count, paths, path_keys, applied_overrides, and applied_patches. The parallel path_keys array preserves exact node identities for the readable paths. An absent dependency has found: false and zero paths.

See Dependency graph for node fields and count definitions.

Common problems

If no usable lockfile exists, run lpm install from the project.

If a package is absent, inspect the complete graph without filters:

lpm graph --format json

For an ambiguous package selector, copy an exact key from the result or error.

If a browser cannot open the HTML report, generate the file with --no-open. Then open the printed path in another browser.

Flags

Argument or flagEffect
[PACKAGE]Select a dependency subtree by name, coordinate, or exact instance key.
--format <tree|dot|mermaid|json|stats|html>Select the output format. Default: tree.
--why <WHY>Explain every path to dependencies with this package name.
--depth <DEPTH>Keep this many graph levels. Must be at least 1.
--filter <FILTER>Match dependency names by substring.
--prodSelect production and optional roots. Conflicts with --dev.
--devSelect development roots.
--no-openWrite HTML without opening a browser. Other formats ignore this flag and warn in human output.
--jsonEmit structured graph or why data.

See global flags for shared options.

See also

  • Dependency graph — interpret graph nodes, edges, and statistics.
  • lpm query — select packages by behavior, state, or relationships.
  • lpm audit — inspect security findings and analysis coverage.
  • Lockfile — understand resolved dependency data.