the example the page told you to write was refused by the version it documents
a hook is a group now, and the pages say so
list what each module publishes, and say what is not on the list
hooks: a module's part wraps the topology's
machine-side hooks: what a topology can run outside its nodes
keep the term in the heading; the purpose belongs in the first line
Kathara does span machines now; lead the deploy section with what you want to do
a Kathara lab across machines needs the bridge plugin
wiki: say what each feature is for, before saying what it does Twenty-two sections opened by restating their own name - "NodeClass defines device types and their basic properties", "Define automatic parameter assignment" - or by going straight into a table. A reader who does not already know why the feature exists learns nothing from the syntax that follows. Each now opens with what it is useful for. The existing text is untouched; this is one paragraph added in front of it. The six class definitions carried the most weight, since the class system is where a topology's shape is decided and "NodeClass defines device types" says nothing about why there is one class per kind of object. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
wiki: say topology where a topology is meant, and stop saying scenario scenario is netroub's word - a configuration together with the events that happen in it, defined in its papers and in its own schema, where a scenario is a topology plus events. This documentation had taken it for what a reader writes, which would have left two projects by the same author using one word for two things. What you write - the DOT file and the YAML that configures it - is a topology, which is how this field already speaks: containerlab calls its own file a topology definition and puts the nodes' images and configuration in it. Basic-Concepts and Home say so before the word is used. Where only the graph is meant the pages now say the DOT file, and topology file is left to mean what a platform reads.
wiki: say what each module is for, and run labs through the entry script The module list mixed a platform with a configuration helper without saying so. Modules are now introduced by what they do for you: platform modules write the file their platform reads, which is where the automation is; software modules help write what runs inside the nodes; assert checks the scenario against itself. Writing a module is a different subject from using one, so the interfaces and their timing moved to a page of their own, along with what a module may and may not say to a scenario. Each platform page now runs its lab through the generated script first and by hand second. That is not a preference: destroy through the script runs the teardown commands, collects the files, and cleans up what the lab left on the machine, and none of it happens when the platform's own command is called directly.
wiki: the last three, and the FRR alternative now builds too The Alternative example gathered {{ .interfaces_ospf_network }} from an interfaceclass that the example never showed, so following it produced a hard failure. The class is there now, and the example was built: the network line does come back from each interface. Module-System's result tree still said r1/frr.conf thirty lines below the same page saying r1/etc/frr/frr.conf. containerlab does not merely omit an empty exec: section - a scenario with no startup template anywhere does not build at all. The page said only the first half.
wiki: make the FRR examples run, and stop claiming what TiNET does not do Module-FRR's two examples were the last that did not work. The first reached for ip_net from a node template, where interface parameters do not exist. The second put FRRVtyshCLI on the startup block that gathers the others, so each gathered block came back quoted inside the outer vtysh command - and its policy: [ip] named a layer where a policy name belongs. Both are replaced by what was built and run: startup gathers, each gathered block carries the format, and the topo.yaml shown is the output of the input above it. TiNET writes a node_configs entry for every node, with an empty cmds: when there is nothing to run - the page had said the entry is left out, since v0.7.0. containerlab does leave its exec: out, and that page was right; the two now say so where they differ. Also: Module-System's result tree still had r1/frr.conf, and put a vtysh command format on a file where it does nothing.
wiki: the two things that were being left for next time A literal {{ }} in a generated file is filled in by dot2net without a word - the file comes out looking right and carrying a value the downstream tool was meant to choose. That is worth a section of its own in Template-System, with the two ways to write it out and the two settings that exist because writing it out by hand is easy to get wrong. Best-Practices has the design side: decide which of the two tools fills in each value, and do not let both. The platform table gains the row a reader looks for when asking whether a lab can check itself: TiNET has a test: section dot2net does not write yet, Kathara dropped ltest in 3.8.0, containerlab has nothing.
wiki: make the examples run, and say what virtual means now The two Complete Examples printed a loopback address from a scenario that never asked for one, and had no interface policy either - copied out and run, they stopped at 'no segment for layer ip'. Both build now; containerlab's generated topo.yaml is the real output of the example above it. The FRR page told readers to write 'conf t' in a template whose FormatStyle already writes it, which would have produced it twice. Its topology output had no network-mode: none, the platform-node paragraph said kind was unnecessary when only image is, and interface_class: is not a key any more than node_class: was. virtual now has a section: it means something different on a node, an interface and a connection, and since 0.8.0 a virtual interface no longer takes its link with it - which nobody was told. Also: TiNET's shell failure mode is not containerlab's (its output is piped to a shell on the host), FormatStyle-Design carried a backward compatibility section for fields that no longer exist, and four cross-page anchors pointed at headings that were renamed.
wiki: the parts a reader needs that were only in the code What a module may implement and when each hook runs, so that reading a module is possible without reading the framework. What the three platforms differ in, as one table - including the one that catches people, that containerlab and TiNET run a startup command without a shell while Kathara's is a shell script, so a command with && in it works on one and silently does the wrong thing on the others. DOT syntax: xlabel is read on edges and subgraphs, not only on nodes, and why (Graphviz draws label across the picture); a node's label is deliberately not a class. And how a lab spanning machines is drawn. Dropped mountsourcepath, which is documented but never read by anything, and a note promising that legacy FormatStyle field names still work - they were removed, and an unknown key is now an error.
explain what the fields decide, not just that they exist A table row saying provide is 'mount or copy' tells a reader nothing about which to pick. The file definition fields now say what each one decides and links to the section that explains the choice, and the same was done for the param_rule sources and the class combination rules - where the config row was also wrong: two classes defining a config entry of the same name is an error whatever their strength, not a conflict resolved by tier. Module-FRR says where the log actually ends up: inside the container while the lab runs, under collected/<node>/ once it is destroyed, owned by whoever ran the script. That is the question a reader of the FRR page has, and answering it there is worth the repetition. Best-Practices had two sections about building incrementally and no table of contents; it now has one of each, in an order that follows how a scenario is written, plus what multi-host asks of a design. Also: the upgrade page belongs in Getting Started, not under Modules; node_class: is not a key and 0.8.0 rejects it; TiNET's complete example still had sysctls, switches: [] and ./ mounts; a digraph cannot hold --; and virtual on an interface no longer taking its link with it is a breaking change nobody was told about.
fix what the sweep left behind: names, examples, and the rules they depend on The pages written from scratch were checked against the code; the older ones were not, and the site contradicted itself. The default interface prefix said net in the reference and eth in the upgrade page. The frr FormatStyle was called frrVtysh, which never existed. TiNET's mounts had no $PWD and grew a sysctls section it does not generate; containerlab's examples had no network-mode: none, in a page that explains it is there. The tutorial's first YAML example used keys that do not exist, which 0.8.0 rejects outright, and Best-Practices told readers to run subcommands that were never implemented. Added what everything else leans on: how several classes on one object combine and which one wins, scope: group and what a group-scoped file is for, and the per-machine topology and spec files on the two platform pages. Kathara and assert are in the module tables now, so the new page can be reached.
0.8.0: multi-host, the ConfigTemplate field reference, and the assert module YAML-Configuration: the worker group class and what follows from naming it - a topology file per machine, the check against a node in two of them, the bridge replacement for a segment that reaches across - and boundary_crossing_connection_class. Template-System: a reference for the fields of a config entry, which the wiki never had. raw, delimiters, required_link and required_params are in it. Module-System: the assert module. Home: the Kathara page.
0.8.0: file provisioning, the module/scenario boundary, and a Kathara page File-Output: path now decides where a file is written as well as where it goes in the container, which is a breaking change; provide: mount|copy, staging, collect, executable. Module-System: which names may cross between a module and a scenario - class names, value names, and the hooks dot2net owns (startup, teardown). A module class pulled in with use: can add to a hook. Module-Kathara: new. Why the lab sits in a directory of its own, why mounts are directories and what mount_dirs states, and what Kathara cannot express.
fix TiNet -> TiNET, update broken links to File-Output and Module-System
rewrite Module-System: focus on loading, effects, and combining modules
reorganize wiki: split File-Output and Module-System, restructure Home categories