Skip to content

graph

Terminal window
npx graph-spec-cli graph [path] [--format json|mermaid|dot] [--from <concept>]
[--depth <n>] [--rel <name[,name...]>] [--direction out|in|both] [--structure]

Builds the graph and emits it. With no --from, emits the whole thing. With --from, emits only the subgraph reachable from that concept.

This is the command that makes scoped reads possible, and the one an agent uses most.

Flag Effect
--format json (default), mermaid, or dot
--from <concept> Emit only the subgraph reachable from this concept
--depth <n> Limit hops from --from. Default unlimited
--rel <names> Restrict to these relation types, comma separated
--direction out (default), in, or both. Requires --from
--structure Include implicit directory parent to child edges
Terminal window
npx graph-spec-cli graph spec/ --from architecture/validator.component --depth 1

--from accepts either a bare concept ID or the leading-slash reference form used by relations: targets, so a target copied out of frontmatter can be pasted straight in:

Terminal window
npx graph-spec-cli graph spec/ --from /architecture/validator.component.md --depth 1

Narrow further by relation to get exactly the concepts that bear on building something:

Terminal window
npx graph-spec-cli graph spec/ --from architecture/validator.component \
--rel exposes,uses,satisfies --depth 1

--direction decides which way edges are followed. The default out follows edges where the visited node is the source.

Relations that originate elsewhere and merely point at a concept, namely constrains and covers, need --direction in:

Terminal window
npx graph-spec-cli graph spec/ --from architecture/validator.component \
--rel covers --depth 1 --direction in
{
"nodes": [
{ "id": "architecture/validator.component", "type": "Component", "title": "Validator" },
{ "id": "specification/strict-promotion.test-scenario", "type": "TestScenario", "title": "Strict Promotes Warnings" },
{ "id": "specification/validate-golden.test-scenario", "type": "TestScenario", "title": "Validate Golden Bundle" }
],
"edges": [
{ "from": "specification/strict-promotion.test-scenario", "to": "architecture/validator.component", "relation": "covers" },
{ "from": "specification/validate-golden.test-scenario", "to": "architecture/validator.component", "relation": "covers" }
]
}

Edges keep their original orientation in the output. Walking backward changes what is reachable, not what the edge means.

Without --from, --direction has nothing to modify. It is ignored and prints a note to stderr rather than failing, since the whole graph comes back either way.

JSON (default), for programs and agents:

{
"nodes": [{ "id": "...", "type": "...", "title": "..." }],
"edges": [{ "from": "...", "to": "...", "relation": "..." }]
}

Mermaid, for a diagram in a markdown file or a pull request:

Terminal window
npx graph-spec-cli graph spec/ --format mermaid

Emits graph LR with aliased node IDs and relation-labeled edges.

DOT, for Graphviz:

Terminal window
npx graph-spec-cli graph spec/ --format dot | dot -Tsvg -o spec.svg
Terminal window
npx graph-spec-cli graph spec/ --structure

Adds implicit directory parent to child edges with the kind child. These are not profile relations and are excluded by default. They follow --direction too, so in from a child walks up to its parent.

An edge is emitted only when both endpoints are in the selected node set. A slice is therefore always a valid graph on its own, and unresolved targets never appear as phantom nodes. Dangling references are coverage’s business.

Code Meaning
0 Success
2 Unknown format, unknown relation name, bad --depth, bad --direction, unresolved --from, or unreadable bundle

An unresolved --from echoes what you typed:

$ npx graph-spec-cli graph spec/ --from /nope/missing.md
error: --from concept not found: /nope/missing.md
  • --depth counts hops, so --depth 1 is the concept plus its immediate neighbours.
  • --rel validates names against the vocabulary and exits 2 on an unknown one, rather than silently returning nothing.
  • Traversal skips unresolved edges, so it never walks into a concept that does not exist.