Skip to main content

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.

nettopo is a working title — see PROJECT_SPEC.md section 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_id yet (no phase parses show etherchannel summary), so it is currently a no-op against real captures. See docs/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 in docs/architecture.md.

Installation

Not yet published to PyPI (publishing happens on tagging v0.1.0 after this PR merges, via .github/workflows/publish.yml). 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, 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.

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

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

MIT

Metadata

Release files for nettopo 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nettopo 0.2.0
File Size Uploaded
nettopo-0.2.0.tar.gz 46.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nettopo 0.2.0
File Interpreter ABI Platform
nettopo-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 85.8 kB

Release files / nettopo-0.2.0.tar.gz

Download URL nettopo-0.2.0.tar.gz
Size 46.8 kB
Tags Source
SHA-256 checksum
How to use checksums
66fc36a24908de3ed62646dd73dda3baf99d222c21e485f9fb4d6bedb3624db1
BLAKE2b-256 checksum
How to use checksums
cf3978b48e0415360de901556343dee5b30678774e1cbaa8ece62090e1ce4639
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 7, 2026.

Transparency log

Release files / nettopo-0.2.0-py3-none-any.whl

Download URL nettopo-0.2.0-py3-none-any.whl
Size 39.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b59339b5dbda727103e355f061792a0baf916b1941ebb0f64d0fa18a0129517c
BLAKE2b-256 checksum
How to use checksums
0deb34051a852434efe6ba5a5320182a674c4dd3db9b87402229cd0a7e0ec229
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 7, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page