netviz GitHub

netviz layout

Store the diagram's arrangement in the inventory, so a diagram that has been arranged stays arranged.

Everywhere else in netviz, the picture is derived: you describe the network and Graphviz decides where things go. That is the right default and it is what render still does. But it means the diagram cannot be edited — drag a switch to where it belongs and the next render puts it back, because nothing in the tree remembers that you moved it. netviz layout is what makes the arrangement part of the model: a kind: layout document holding a position per node — and, when asked, the route each link takes and the style it is drawn in — scoped by view, loaded, validated and edited like everything else.

Once a view is arranged, render reproduces it exactly — the same coordinates in the SVG, the same coordinates in the HTML, the same coordinates in the JSON export.

docs/schema.md §18 is the document format. docs/rendering.md is how the renderers honour it. This page is the reference for the command.

Synopsis

netviz [GLOBAL OPTIONS] layout [OPTIONS]

The four things it does

With no flags it reports. One row per view: how much of the drawing the stored arrangement decides, how many nodes are placed, and how many stored keys name nothing the diagram has.

$ netviz layout --layer l1 --layer l2
layout documents: layout
VIEW  MODE     NODES  EDGES  GROUPS  STALE
----  -------  -----  -----  ------  -----
l1    fixed    8/8    0/7    0/0     -
l2    partial  6/8    0/7    0/0     1

MODE is the decision a render makes from what is stored:

Mode What is stored What a render does
auto nothing for this view lays the graph out from scratch, exactly as it always did
partial some of the nodes pins those and lets the engine place the rest around them
fixed every node reproduces the arrangement point for point, with the layout engine placing nothing

--write seeds and completes. On a view with no arrangement it runs the automatic layout once and persists the result, which is what makes the diagram editable from then on. On a view that is already arranged it places only what is not yet placed — adding a switch and re-seeding must not throw away an afternoon of arranging. --replace is how you ask for the whole view to be laid out afresh.

netviz layout --write                       # place what is not placed yet
netviz layout --write --replace             # lay every node out afresh
netviz layout --write --engine circo        # ... with a different engine
netviz layout --write --layer l1 --layer l3 # arrange two views
netviz layout --write --dry-run             # print the diff, write nothing

What is written is a fixed point: the coordinates stored are the coordinates the next render produces, not the ones the seeding engine happened to report. (The two differ — a no-op render normalises the drawing to the origin — and an arrangement that only settled on the second render would be a poor thing to promise.)

--prune drops what is gone. Deleting a switch leaves its coordinates behind. They draw nothing, but they accumulate, and W138 reports them until this clears them. A prune on a clean tree writes no files.

--clear goes back to automatic. The arrangement for the selected views is dropped; a layout document left holding nothing is removed, and so is its file if it held nothing else.

The display options are inputs, not decoration

--show-ips, --show-vlans, --group-by-namespace, --icons, --rankdir and the rest are on this command for a reason that is easy to miss: a label decides how big a node is, and how big the nodes are decides where the layout puts them. An arrangement seeded with --no-show-ips and rendered with addresses on is an arrangement of boxes that are now too small for their contents.

So seed with the options you render with. Better, put them in netviz.toml — this command reads [render] and --profile exactly as render does, which is the only way to be sure the two cannot drift apart.

The filter options are deliberately absent. An arrangement covers a view; one seeded from three of a hundred devices would leave the other ninety-seven unplaced and the diagram permanently half-arranged.

What it stores, and what it does not

Positions, in points, y upwards, a position being the centre of the node — Graphviz's coordinate system, unchanged, because the whole point is to be able to hand it straight back.

Group boxes too, when the render groups by namespace: the no-op layout engine does not draw clusters, so netviz draws them itself from the stored box, which means the frame is where you put it rather than wherever a layout happened to land. Its caption sits centred above the frame rather than inside it — docs/follow-ups.md §17 explains why that is not a matter of taste.

--waypoints also stores the routes, as the interior bends of each link — the two ends of a route are always the nodes themselves, so a stored route survives either device being dragged. It is off by default because a seeded route is a handful of points per link that the render recomputes identically, and that is a lot of noise for no decision; a hand-placed bend is a decision, and the flag is how you get a starting point to drag one from. It brings the sizes of the nodes those routes leave from with it, which is the one case where a stored size is worth having: a route netviz computes has to stop at the shape it runs into, and netviz cannot measure a label. Every other node is left sized by its label, because Graphviz derives the same box from the same label on every run and a stored size would go stale the moment a device grew an interface (docs/follow-ups.md §16).

--routing records how this view's links are drawnspline, orthogonal or straight — as views.<view>.routing. The same flag every other command takes, doing both jobs at once here: the seeding run draws in that style, and --write then records it, so what is stored is what was on screen. It is a default: a link that pins a style of its own keeps it. To take the setting back out, delete the one line it wrote — a generated file that has to be hand-edited to be undone is a poor thing, but a --routing "" that meant "remove" would be one keystroke away from --routing meaning "leave alone", and that is worse.

A style pinned on one link, and where a link's label sits, are decisions a person takes rather than ones a layout run can seed, so they are written by the canvas editor of netviz web instead; docs/rendering.md is what all three draw as.

Writes go through the edit layer

Every change is a netviz edit operation (set-geometry), which means it inherits the whole write path: comments and formatting in a hand-arranged file survive, --dry-run shows the exact hunk, the tree is loaded and validated as it would be before anything is written, and a file that changed on disk since it was read is refused rather than overwritten.

It also means re-seeding an unchanged diagram writes nothing at all — a stored position: [240, 396] and a computed {x: 240, y: 396} are recognised as the same position, so a generated file does not churn on spelling. A position is written on one line for the same reason: a diff of an arrangement should read as a list of what moved.

Arguments and flags

Takes no positional arguments.

Flag Value Default Meaning
--layer [physical|l1|l2|l3|ipam|overlay|routing|rack|power|identity|netns|security] l1 Which view to arrange. Repeatable; each view is arranged separately.
--engine [dot|neato|fdp|sfdp|circo|twopi] dot Graphviz engine to lay the diagram out with when seeding. dot is the hierarchical layout netviz draws with; circo suits a ring, fdp and neato a flat mesh.
--write off Run the layout once and store the result, making the arrangement editable.
--clear off Drop the stored arrangement, so the view is laid out from scratch again.
--replace off With --write, lay every node out afresh instead of keeping what is already arranged and placing only the rest.
--prune off Drop geometry for elements the inventory no longer declares.
--waypoints off Also store the bends each link is routed through, and the sizes of the nodes they leave from. Off by default: the render recomputes an equivalent route from the node positions, and a handful of points per link is a lot of noise. Turn it on to get a starting point that can then be dragged.
--name NAME layout metadata.name of the layout document to write into or create.
--namespace PATH Folder to declare the layout document in. The inventory root by default.
--file PATH File to write a new layout document to, relative to the inventory root. Chosen by the layout conventions when absent.
--show-ips, --no-show-ips --show-ips Print configured IP addresses on the nodes.
--show-vlans, --no-show-vlans --show-vlans Annotate nodes and links with VLAN membership.
--annotations, --no-annotations --annotations Draw the notes, areas and legends the inventory declares for this view. Turn them off for a diagram that should carry the topology and nothing written about it — a printed page for an audit — and leave them on for one that is being read rather than checked, where the callout is the reason the screenshot is worth attaching to the ticket.
--group-by-namespace off Draw each namespace as a visual group.
--icons THEME|DIR Draw each element as an icon instead of a plain shape. Built in: cisco, none. A directory of images named after element kinds (router.svg, switch.png, ...) also works. Graphviz formats only.
--theme NAME|PATH Apply a stylesheet: selectors by kind, name, namespace, role or label, each mapping onto a style block. Built in: blueprint, mono, none. A path to a 'kind: theme' YAML file also works. An element's own spec.style still wins.
--style, --no-style --style Honour the styles the inventory and the theme declare. --no-style draws the plain diagram from the built-in palette alone, which is the way to read a topology whose stylesheet is in the way. Icons are unaffected: use --icons none.
--tooltips, --no-tooltips --tooltips Carry the full detail of each element — interfaces, addresses, VLANs, cabling — as hover text. Reaches a reader in svg output; png and pdf have nowhere to put it.
--link-template URL Link each element back to the YAML that declares it, e.g. 'https://git.example.com/net/blob/main/{file}#L{line}'. Placeholders: {file}, {line}, {name}, {namespace}, {kind}. dot and svg only.
--element-ids off Give every node, edge and namespace a stable id derived from its name, so the diagram can be deep-linked and styled from outside. dot and svg only.
--max-addresses N 4 Longest address list spelled out under a node before it is abbreviated to 'and N more'. 0 prints the count alone.
--rankdir [tb|lr|bt|rl] TB, top to bottom Layout direction. A wide network reads better left to right; a deep one top to bottom. Honoured by the Graphviz backends and by mermaid.
--routing [spline|orthogonal|straight] whatever the inventory's layout documents say, else spline How links are drawn between the bends they are pinned through: 'spline' is the curve Graphviz draws, 'orthogonal' right angles, 'straight' segment to segment. A default: a link that pins a style of its own keeps it. Honoured by the Graphviz backends, the JSON export and the editor. 'netviz layout --write' records it in the view it arranges, so the choice is the inventory's rather than the command line's from then on.
--avoid, --no-avoid avoid Route orthogonal links around the boxes they are not attached to instead of straight across them. Only applies to an arranged diagram drawn with '--routing orthogonal': a spline has nothing to route around, and an unarranged one is routed by Graphviz, which already avoids nodes. A bend you placed yourself is never moved — routing fills the segments between them. '--no-avoid' is the local Z-and-L every orthogonal diagram was drawn with before this existed.
--title TEXT Caption for the diagram.
--profile NAME Apply the [profile.NAME] block of netviz.toml on top of its [render] table. Explicit flags still win over both.
--show-config off Print the settings this invocation resolves to, and where each one came from, then exit without doing any work.
-n, --dry-run off Write nothing; print the unified diff the edit would apply.
--json off Print the applied operations and their inverses as JSON, so a caller can keep an undo stack.
--force off Write even when the edit would introduce a new error. The check for files that changed on disk is never skipped.

Exit codes

Code Meaning
0 The arrangement was reported, or written.
1 The inventory has errors, or the edit would introduce one, or a file changed on disk.
2 Usage error — --write and --clear together, --replace without --write.
3 The inventory could not be read.
5 Graphviz is not installed, or the layout failed.

See also