netviz watch
netviz watch re-renders whenever a file in the inventory changes, optionally
serving the result on a page that reloads itself. Every cycle is the same load,
validate and render netviz render performs, followed by a
timestamped status line and any findings. It is the command to leave running in
a second terminal while you edit YAML in the first.
Synopsis
netviz [GLOBAL OPTIONS] watch [OPTIONS]
The status line
One line per cycle, with the time, the status and what came of it:
09:41:02 ok 23 nodes, 26 edges → topology.svg (128 ms)
09:41:37 invalid 1 error; keeping the render from before
errors (1):
sites/hq/links.yaml#0:12 E001 cable 'sites/hq/cbl-07' endpoint sw-hq:port9: no element named 'sw-hq' is declared in this inventory
A failed cycle changes nothing. The file written by --output keeps its last
valid contents and the preview keeps serving the last valid diagram, so a
half-typed document never blanks the picture you are working from — which is why
the line says keeping the render from before rather than reporting a size of
zero. Nothing ends the loop except Ctrl-C: a syntax error, a deleted root, a
--neighbors-of target that no longer resolves are all statuses, not crashes.
With --output the file is rewritten atomically, so a reader — a browser with
the SVG open, a static site build — sees the old diagram or the new one, never
half of each. Naming a file inside the tree being watched is fine: the render's
own output is excluded from the watch, which is what keeps the loop from feeding
itself forever.
Giving neither --output nor --serve is allowed and warned about: each render
is then checked and discarded, which is occasionally what you want and usually
not what you meant.
What triggers a render
Only YAML documents, netviz.toml and .netvizignore trigger a render; an
editor swap file or a rendered diagram does not, and neither does anything under
a directory the loader skips (.git/, _drafts/, …) — the same rule the loader
itself applies, so what the watcher reacts to is what the inventory contains. A
single-file inventory is watched through its directory, because editors replace a
file rather than rewrite it and a watch on the file itself would not survive the
first save.
--debounce is how long a burst of filesystem events is collected before
re-rendering. One editor save is several events — a temporary file, a rename, a
metadata change — and re-rendering each of them would render three times and show
the middle one.
The default is 300 ms on Linux and 700 ms on macOS and Windows, because the
window has to be wider than the span those events arrive over and that span
belongs to the backend rather than to the editor. inotify delivers each event as
it happens, so one save lands within a millisecond or two. FSEvents coalesces
and delivers on its own schedule, and ReadDirectoryChangesW spreads a
save-by-rename noticeably further — often as two bursts, which at 300 ms would be
two renders for one keystroke.
Raise it for a large inventory, lower it if you want the diagram to keep up with you and do not mind the occasional double render.
Every render option applies
Every filter and display option of netviz render applies here too —
--tooltips, --link-template and --element-ids included, which is what makes
watch -f svg -o topology.svg keep an interactive diagram up to date. -f html works the same way, repeated --layer included, so watch -f html -o topology.html --serve gives you the whole interactive page, re-rendered as you
type. -f defaults to svg here rather than dot, because a live preview wants
a picture.
docs/rendering.md explains the layers, the filters, the
aggregation and the display options themselves; this command adds nothing to
them and changes none of their defaults.
The live preview
--serve also hosts the render over HTTP. The page polls once a second and swaps
the diagram in when it changes — polling rather than server-sent events keeps the
client a dozen lines of dependency-free JavaScript.
The preview is bound to loopback and stays there unless you say otherwise. An
inventory describes internal network topology — addresses, VLANs, what is plugged
into what — so --host is the explicit act of publishing it, and doing so prints
a warning. The server answers GET and HEAD on five fixed routes, never turns
a request path into a file name, and refuses a request that reached a loopback
preview under a foreign Host header. It is a development server: do not put it
on a hostile network.
--host and --port describe that server, so both require --serve; given
without it they are a usage error rather than a flag that appeared to work and
never did. --port 0 lets the operating system choose one, and the address
actually bound is printed.
netviz watch --serve # preview at http://127.0.0.1:8080/
netviz watch -f svg -o topology.svg # just keep a file up to date
netviz watch --serve --layer l2 --vlan 10 --title vlan10
netviz watch --serve --host 0.0.0.0 --port 9000 # deliberate, and warned about
Arguments
Takes no positional arguments.
Options
| Flag | Value | Default | Meaning |
|---|---|---|---|
-f, --format |
[dot|svg|html|png|pdf|mermaid|json] |
svg |
Output format. Defaults to svg, which is what a live preview wants. |
-o, --output |
FILE |
— | Rewrite this file after every successful render. |
--namespace |
NS |
— | Keep only elements in this namespace or below it. Repeatable. |
--vlan |
VID |
— | Keep only elements participating in this VLAN. Repeatable. |
--kind |
[switch|router|firewall|hub|computer|server|adapter|patchpanel|pdu|user|group] |
— | Keep only elements of this kind. Repeatable. |
--name |
GLOB |
— | Keep only elements whose name matches this glob. Repeatable. |
--neighbors-of |
NAME |
— | Keep only the neighbourhood of this element. |
--depth |
INTEGER, >= 0 |
1 |
How many hops --neighbors-of reaches. |
--select |
QUERY |
— | Keep only the elements this query selects, e.g. "kind = switch and not has vrf". The flags above are sugar for the equivalent query and are combined with it; 'netviz query --explain' prints which. See docs/query.md. |
--collapse |
NS |
— | Replace this namespace and everything under it with one node, labelled with what it holds. Links crossing the boundary attach to it; links inside it are counted rather than drawn. Repeatable. |
--collapse-depth |
N |
— | Collapse every namespace N levels deep, counted from the shallowest one that branches: '--collapse-depth 1' is the site-level overview of a tree laid out as sites/ |
--bundle-links, --no-bundle-links |
— | — | Draw parallel links between the same pair of elements as one edge, with the count in the label. Members of a declared 'lag' interface are bundled either way unless --no-bundle-links is given, since the inventory already says they are one logical link. |
--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. |
--layer |
[physical|l1|l2|l3|ipam|overlay|routing|rack|power|identity|netns|security] |
l1 |
l1 draws the physical topology; l2 annotates it with VLANs; l3 draws IP subnets and the elements addressed in them; ipam draws the address plan — the same prefixes without the devices, nested inside the blocks they came out of and showing how full each is; overlay draws the tunnels; routing draws the BGP sessions and OSPF adjacencies, clustered by VRF; physical adds the patch panels l1 splices out; rack draws a front elevation per rack; power draws the PDUs and the feeds into everything they power; identity draws the users and groups; netns opens each machine up into the network stacks inside it, joined by their veth pairs; security draws the firewall zones and what the policy lets cross between them. Repeatable for -f html, which draws each layer and puts a switcher over them. |
--strict |
— | off | Treat warnings as errors. |
--force |
— | off | Proceed even when validation failed. The result may not match the files. |
--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. |
--serve |
— | off | Also host the render over HTTP, on a page that reloads itself. |
--host |
ADDRESS |
127.0.0.1 |
Address --serve binds to. The default keeps the preview on this machine; an inventory describes internal topology, so publishing it is an explicit act. |
--port |
INTEGER, 0-65535 |
8080 |
Port --serve binds to. 0 lets the operating system choose one. |
--debounce |
MS |
300 on Linux, 700 on macOS and Windows | How long a burst of filesystem events is collected before re-rendering. |
Exit codes
A watch is ended by Ctrl-C, which is how the command is meant to finish and not a failure. Everything an inventory can do wrong is a status line instead of an exit status.
| Code | Meaning |
|---|---|
| 0 | The loop ran and was stopped with Ctrl-C. |
| 2 | Usage error: --host or --port without --serve, an unusable netviz.toml. |
| 6 | --serve could not bind its address — usually a preview already running on that port. |
See also
netviz renderanddocs/rendering.md— the render every cycle performs, and every option this command inherits.netviz web— the same live feedback for a document stream you edit in the browser rather than a tree you edit on disk.docs/validation.md— the findings a cycle reports, and what--strictpromotes.