Network automation utilities for discovery, inventory, configuration collection, health checks, safe configuration changes, and vendor-aware parsing. The core CLI supports Python 3.9 or later; the optional Textual TUI requires Python 3.10 or later.
| Area | Supported interface |
|---|---|
| Discovery | Ping, SNMPv2c, CDP/LLDP, and optional SSH enrichment |
| Inventory | YAML/JSON inventory, filtering, and Ansible export |
| Operations | Health, BGP, VLAN, interface checks, config collection, and backups |
| Changes | Semantic diff, dry-run-safe push, rollback, and change plans |
| Access | Direct SSH/Telnet, per-device jump hosts, and active bastion routing |
| Optional tools | Textual TUI, reports, and Ansible helpers |
Supported Netmiko device types include Cisco IOS/IOS-XE/IOS-XR/NX-OS, Nokia SR
OS/SRL, Brocade FastIron/NOS, Palo Alto PAN-OS, Juniper Junos, and Arista EOS.
Use the exact device type expected by Netmiko in vendor fields.
The maintained installer creates a user-local environment at ~/.venv/netops
and installs the TUI, scanning, HTML report, and documentation build extras.
It also builds an offline documentation site at
~/.local/share/netops-toolkit/docs/index.html. It selects the newest
compatible installed Python (3.9+) for that environment, so netops and
netops-tui use the same interpreter. If no compatible Python is installed,
uv provisions one. It does not require sudo.
curl -sSL https://raw.githubusercontent.com/plures/netops-toolkit/main/install.sh | bash
source ~/.venv/netops/bin/activate
netops --helpFor an offline installation, download and extract a release archive, then run
./install.sh from its root.
If uv reports Disk quota exceeded or No space left on device, the install
did not complete; activate neither the partial environment nor an unrelated
/home/... path. Confirm the actual home directory with echo "$HOME", then
free the uv cache and retry:
deactivate 2>/dev/null || true
UV_BIN="$(command -v uv || true)"
[ -x "$UV_BIN" ] || UV_BIN="$HOME/.local/bin/uv"
[ -x "$UV_BIN" ] || UV_BIN="$HOME/.cargo/bin/uv"
"$UV_BIN" cache clean
quota -s 2>/dev/null || true
df -h "$HOME" /tmp
curl -sSL https://raw.githubusercontent.com/plures/netops-toolkit/main/install.sh | bash
source "$HOME/.venv/netops/bin/activate"
netops --helpWhen your home directory cannot hold the environment, place the virtual environment, uv cache, and uv-managed Python installs on a filesystem with adequate user quota:
export NETOPS_VENV_DIR=/path/with/space/netops
export NETOPS_UV_CACHE_DIR=/path/with/space/netops-uv-cache
export UV_PYTHON_INSTALL_DIR=/path/with/space/netops-uv-python
curl -sSL https://raw.githubusercontent.com/plures/netops-toolkit/main/install.sh | bash
source "$NETOPS_VENV_DIR/bin/activate"Clone the repository and install into a virtual environment. This is a per-user operation; an elevated shell is not required.
git clone https://github.com/plures/netops-toolkit.git
cd netops-toolkit
py -3 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e ".[tui,snmp,report]"
netops --helpDownload the ZIP from Releases, extract it, then run in PowerShell:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\netops-toolkit-<version>\install.ps1"The installer finds the newest compatible Python (3.9+) registered on the machine, then creates a virtual environment under %LOCALAPPDATA%\netops-toolkit. Both netops and netops-tui run from that same environment. It builds offline documentation at %LOCALAPPDATA%\netops-toolkit\docs\index.html, adds a per-user Start menu shortcut, and does not require administrator rights.
To see which interpreter the installer will use without making changes:
.\install.ps1 -CheckPythonThe installed netops and netops-tui launchers use that managed environment.
When running python -m netops directly, Python necessarily uses the
interpreter that you explicitly invoked.
python3 -m venv ~/.venv/netops
source ~/.venv/netops/bin/activate
pip install -e ".[tui]" # Textual terminal UI
pip install -e ".[snmp]" # SNMP discovery
pip install -e ".[report]" # HTML report API
pip install -e ".[report-pdf]" # HTML and PDF report API
pip install -e ".[ansible]" # Ansible helpers
pip install -e ".[dev]" # test and lint toolingCopy the example inventory and replace the sample addresses and credentials.
cp examples/inventory.yaml my-inventory.yaml
netops health --inventory my-inventory.yaml
netops backup --inventory my-inventory.yaml --output ./backupsFor a single device, the module-level collector is the direct interface:
python -m netops.collect.config \
--host 10.0.0.1 --vendor cisco_ios --user adminSupply NETOPS_PASSWORD rather than placing a password in shell history:
export NETOPS_PASSWORD='replace-me'
netops health --host 10.0.0.1 --vendor cisco_ios --user adminOn PowerShell:
$env:NETOPS_PASSWORD = 'replace-me'netops --help currently lists netops report, but that dispatcher command is not
usable because netops.report.generator has no CLI entry point. Use the report
Python API or python -m netops.report.health_dashboard instead.
| Command | What it does |
|---|---|
netops scan |
Discover devices; use netops scan --help for scan flags |
netops health |
Run cross-vendor CPU, memory, interface, and log checks |
netops backup |
Collect timestamped configuration backups from inventory |
netops push |
Dry-run-safe configuration push; requires --commit to modify a device |
netops diff |
Compare configuration files semantically or as unified/JSON diff |
netops bastion |
Connect, check, or disconnect the workstation-wide SSH bastion |
netops tui / netops-tui |
Launch the optional Textual TUI |
Additional documented module CLIs include:
python -m netops.check.bgp --inventory my-inventory.yaml
python -m netops.check.vlan --inventory my-inventory.yaml --expected-vlans 10,20,30-50
python -m netops.check.interfaces --host 10.0.0.1 --vendor cisco_ios
python -m netops.change.plan plan --host 10.0.0.1 --desired desired.cfg --export plan.json
python -m netops.core.vault initSee the online CLI reference for the verified flags and safe change workflow.
Select a reachable SSH bastion once, then normal TCP device connections from the toolkit are routed through it. No device inventory is required up front.
netops bastion connect --host bastion.example.com --username netops --password-stdin
netops bastion statusThe password is read from standard input and is not stored in the active
bastion state file. Use netops bastion disconnect when the route is no
longer required. SSH forwarding is TCP-only: scan traffic behind an active
bastion uses SSH discovery rather than local ICMP/UDP SNMP probing.
For a per-device compatibility configuration, see SSH jump-host tunneling. For the recommended workstation-wide mode, see Active Bastion Routing.
defaults:
username: admin
transport: ssh
devices:
core-rtr-01:
host: 10.0.0.1
vendor: cisco_ios
role: core
site: dc1
groups: [routers, core]The online inventory guide explains all available fields and exports. Never commit passwords or SNMP community strings to a shared repository; use local inventory files, environment variables, or the encrypted vault as appropriate.
Browse the complete, release-matched documentation at plures.io/netops-toolkit, including getting started, command reference, scanner and bastion guides, configuration changes, and the Python API.
Build the documentation site locally with pip install -e ".[docs]" followed
by mkdocs build --strict.
pip install -e ".[dev,tui]"
python -m pytest
ruff check netops testsFocused tests do not contact real devices. Some optional TUI and scanner tests require their corresponding extras.
netops-toolkit is source-available under the Business Source License 1.1.
Personal and non-commercial use is permitted under its Additional Use Grant;
production use outside that grant requires a commercial license from Plures. Each released version
changes to Apache License 2.0 no later than four years after its first public
distribution. For commercial terms, contact licensing@plures.io.