This release is a pre-release and may not be stable for production use.
nettopo
A Python CLI that reads saved Cisco show command outputs (files only — no live
device connections in v1) and generates network diagrams in draw.io format with
Cisco icons, plus the intermediate data as CSV tables.
Four diagram views are produced from the same parsed data model:
- L2 — physical/link-layer topology from CDP/LLDP, with interface labels and MLAG.
- STP — per-VLAN Rapid-PVST spanning-tree state (root, bridge IDs, priorities, port roles/states).
- HSRP — first-hop redundancy per SVI (virtual IP, priority, active/standby/listen).
- BGP — BGP neighbor (session) graph.
nettopois a working title — seePROJECT_SPEC.mdsection 1.
Status
Phase 4 — STP. nettopo stp -i <dir> now renders real per-VLAN spanning-tree
draw.io diagrams: the root bridge is highlighted, links are colored by forwarding vs
blocking port state and labeled with role/state at each end, and --vlan N or
--group-mode per-vlan|strict|topology (with --all to write every resulting diagram)
select which VLANs are rendered. stp.csv now includes both base and effective bridge
priority. nettopo l2 -i <dir> (Phase 3) renders devices styled with Cisco icons
(render/icons.py) by inferred DeviceRole, with per-end interface labels and
--endpoints all|network-only filtering. Output is post-processed by lucidify by
default (--no-lucidify to skip it) so link labels survive Lucidchart import.
hsrp, bgp, and all still report "not implemented". See the delivery plan in
PROJECT_SPEC.md and the
open issues for the phased build-out.
Known gap: MLAG/port-channel grouping in the L2 view is implemented and tested against the data model, but no shipped parser populates
Interface.po_idyet (no phase parsesshow etherchannel summary), so it is currently a no-op against real captures. Seedocs/architecture.md.Pending manual step: Cisco
mxgraph.cisco.*draw.io stencils are a confirmed requirement but may degrade on Lucidchart import (Lucid uses a different shape library). This still needs a real Lucid import to validate — Phase 4 proceeded on the same rendering approach without it, since that validation requires interactive Lucid access this project's automation doesn't have — see the checklist indocs/architecture.md.
Installation
pip install nettopo
Pre-releases (0.3.0rc1 and the like) are published from the same pipeline but pip
skips them unless asked: pip install --pre nettopo, or pin the exact version. Each
release is published to PyPI by .github/workflows/publish.yml when a v* tag is
pushed. To install from source for development:
git clone https://github.com/isrferna/nettopo.git
cd nettopo
pip install -e ".[dev]"
Requires Python 3.11+.
Usage
nettopo [--log-level LEVEL] <command> [options]
Every command reads a directory of saved capture files (see
Preparing captures below) and writes into an output directory,
creating it if needed. parse, l2, and stp are implemented; hsrp, bgp, and all
are scaffolded but not yet implemented (running them prints '<command>' is not implemented yet. and exits with status 1 — see Status).
Global option
| Option | Values | Default | Meaning |
|---|---|---|---|
--log-level |
DEBUG, INFO, WARNING, ERROR, CRITICAL |
INFO |
Logging verbosity. Goes before the subcommand: nettopo --log-level DEBUG l2 -i ./captures. |
Options common to every command
| Option | Values | Default | Meaning |
|---|---|---|---|
-i, --input |
directory path | (required) | Directory of saved device captures to read. See Preparing captures. |
-o, --output |
directory path | ./output |
Directory to write generated output into (created if it doesn't exist). |
--platform |
an ntc-templates platform name | cisco_ios |
Fallback platform used to pick the right parsing template when a device's own platform can't be detected from its show version output. IOS and IOS-XE both use cisco_ios. |
--no-lucidify |
flag | off | Skip the Lucidchart-import-friendliness post-process (render/lucidify.py) on generated .drawio files. Only affects commands that render diagrams (l2, stp; later hsrp, bgp, all) — parse ignores it. |
nettopo parse
Ingests captures, builds the data model, and writes every CSV table — no diagrams. This is the primary debugging aid: if a diagram looks wrong, inspect the CSVs first to localize the fault to parsing vs. rendering.
nettopo parse -i ./captures -o ./output
Writes output/csv/devices.csv (including each device's serial, from its own
show version or from the name a Nexus neighbor advertises), interfaces.csv,
neighbors.csv, vlans.csv, stp.csv (base and effective bridge priority — see
PROJECT_SPEC.md §6), and header-only hsrp.csv/bgp.csv
until Phases 5–6 add those parsers.
One row per device and per adjacency, regardless of how many names its neighbors use for
it: CDP and LLDP disagree constantly (nxos-core1 vs nxos-core1(FDO21120U5D) vs
nxos-core1.example.com), and those spellings are correlated into one device before the
model is built — see
PROJECT_SPEC.md §5.2.
nettopo l2
Renders the physical/link-layer topology (from CDP/LLDP) as a draw.io diagram: nodes are devices styled with Cisco icons by inferred role, links carry per-end interface labels, and physical links sharing a local port-channel membership are grouped into one rendered link (MLAG).
| Option | Values | Default | Meaning |
|---|---|---|---|
--endpoints |
all, network-only |
all |
all includes every discovered device. network-only drops any device that isn't a source capture and wasn't reported by a neighbor with Router/Switch CDP/LLDP capabilities (i.e. drops hosts/phones, keeps the network). |
nettopo l2 -i ./captures --endpoints network-only
Writes output/l2/l2_full.drawio (endpoints all) or
output/l2/l2_network-only.drawio (endpoints network-only).
nettopo stp
Renders per-VLAN Rapid-PVST spanning-tree diagrams: switches only, root bridge
highlighted, links colored by forwarding (green) vs. blocking (red) port state and
labeled with role/state at each end. Node labels show the bridge MAC and effective
priority (base priority is in stp.csv).
| Option | Values | Default | Meaning |
|---|---|---|---|
--vlan |
VLAN id, e.g. 10 |
(none) | Restrict to a single VLAN's diagram. Mutually exclusive with --group-mode. |
--group-mode |
per-vlan, strict, topology |
per-vlan |
How to group VLANs that would render identically. per-vlan: one diagram per VLAN, no grouping. strict: group VLANs whose root, bridge priorities, and port roles/states all match. topology: group VLANs whose root and port roles/states match, ignoring configured priorities (a looser match than strict). Mutually exclusive with --vlan. |
--all |
flag | off | Write every resulting diagram (one per VLAN, or one per group under --group-mode) into output/stp/. |
Either --vlan or --all is required — with neither, there's no single sensible
default to render out of a potentially many-VLAN model, so the command exits with an
error asking you to pick one.
nettopo stp -i ./captures --vlan 10 # one diagram, VLAN 10 only
nettopo stp -i ./captures --all # one diagram per VLAN
nettopo stp -i ./captures --all --group-mode strict # grouped by exact match
nettopo stp -i ./captures --all --group-mode topology # grouped by topology only
Filenames: output/stp/stp_vlan10.drawio for a single VLAN; for a group, a sorted,
filesystem-safe name listing every VLAN it covers, e.g.
output/stp/stp_vlans-10_20_30.drawio.
nettopo hsrp, nettopo bgp, nettopo all — not yet implemented
These subcommands parse their arguments (hsrp already accepts the same
--vlan/--group-mode/--all options as stp) but every run currently exits with
status 1 and logs '<command>' is not implemented yet.. They land in Phases 5–7 — see
PROJECT_SPEC.md §14.
Preparing captures
The -i/--input directory holds one text file per device. Each file concatenates the
outputs of several show commands, each preceded by that device's prompt line
(hostname#show ...) — this is how nettopo both identifies the device as a source
device (as opposed to one only ever mentioned by a neighbor) and splits the file back
into per-command sections. Which commands each view needs is listed in
PROJECT_SPEC.md §4; tests/fixtures/captures/
has worked examples. Files are read as utf-8-sig, so a leading UTF-8 BOM is handled
transparently.
See PROJECT_SPEC.md §9 for the CLI design rationale.
Documentation
PROJECT_SPEC.md— scope, architecture, data model, CLI, delivery plan.docs/architecture.md— components, call flow, design decisions.CLAUDE.md— engineering conventions (workflow, coding principles, security review).CHANGELOG.md— release history.
Contributing
Work is tracked as GitHub issues, one per delivery-plan phase (see PROJECT_SPEC.md
section 14). Each change lands via a pull request from a feat/…/fix/… branch into
main; direct pushes to main are disabled. See CLAUDE.md for the full
workflow and coding conventions.
Security
This tool makes zero network connections by design — it only reads local capture
files. See PROJECT_SPEC.md for the
full OWASP-adapted security review.
License
Metadata
Release files for nettopo 0.3.0rc1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nettopo-0.3.0rc1.tar.gz | 53.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nettopo-0.3.0rc1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 96.4 kB
Release files / nettopo-0.3.0rc1.tar.gz
| Download URL | nettopo-0.3.0rc1.tar.gz |
|---|---|
| Size | 53.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5c9792b76eb3d6c4c9290091e2f2f1998675791cef30e8cbe50509a3a41093bf
|
|
BLAKE2b-256 checksum How to use checksums |
67ff7a97cf1a98e37ddbddfaadf57fbccc04d9dd59afe9490dfb497666fa49f1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 10, 2026.
Transparency logRelease files / nettopo-0.3.0rc1-py3-none-any.whl
| Download URL | nettopo-0.3.0rc1-py3-none-any.whl |
|---|---|
| Size | 43.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b4823ba5d8bbdbbf55fc563a3f9150852340483387b5358c2a435c739c6a3288
|
|
BLAKE2b-256 checksum How to use checksums |
275cf242ec54bfc4f5644870a32e9fb43f3643ffaf47cb8065b1df8fc2cb9b8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 10, 2026.
Transparency log