Multivendor Network CLI Tools is a zero-dependency, single-file HTML reference for network engineers that puts 52,031 CLI commands across 17 vendors and tools into one searchable, filterable, deep-linkable browser page.
It solves the everyday pain of juggling per-vendor syntax — letting engineers search, compare commands concept-aligned side by side, and generate vendor-correct automation snippets (NETCONF, ncclient, Netmiko, Ansible, Bash) pre-filled from their own command values.
An offline, stdlib-only Python pipeline turns published vendor docs — and a live 10-node Docker FRR lab — into one deduped commands.json that GitHub Pages serves statically. No backend, no build, no JS dependencies.
Search, compare, and automate across 17 CLIs — all from one static file.
📚
52,031 commands, 17 vendors, one page
Arista EOS, Cisco IOS/IOS-XE/ASA/NX-OS, Juniper Junos, FRR, VyOS, Huawei VRP, Aruba AOS-CX, Extreme EXOS, FortiOS, PAN-OS, Mikrotik RouterOS, NVIDIA Cumulus NVUE, Nokia SR Linux, SONiC, plus Microsoft PowerShell, Linux iproute2, and Wireshark tshark — all searchable in a single static HTML file.
🪟
Three view modes
Cards (auto-fit grid grouped by category), Table (sortable, exportable to CSV/Markdown/JSON/TXT), and Compare — a concept-aligned, N-vendor-aware matrix that lines up Cisco's neighbor row with Junos's peer row, paginated and virtualized for the full corpus.
🔧
Automate drawer (YANG + SSH)
Regex-extracts your IP/VLAN/ASN/interface from a command and renders vendor-correct NETCONF XML, ncclient Python, Netmiko, NAPALM, and Ansible tasks pre-filled with your values across 15 model-driven patterns, with a universal SSH fallback for every command.
🔐
Secret mode for snippets
Toggle how snippets read credentials — Inline (demo only), .env via python-dotenv (default, safer pasteboard), or OS keyring — and every snippet re-renders in place with a matching .env.example / keyring set one-liner.
🔀
Concept-aligned translation
A 37-entry CONCEPT_SYNONYMS table normalizes semantic intent (bgp:peer, ospf:auth, …) so equivalent commands align across vendors; conceptKey() drives Compare-view row alignment and openEquivalents() adds a "See equivalents" drawer.
🔗
Shareable, deep-linkable workspace
Filters, view, search, favorites, and the cross-vendor CLI Builder queue serialize into a base64 ?ws= URL (plus readable ?cat=BGP&view=compare&v=Juniper params) so a shared link recreates exactly what you saw.
⚡
Instant cache-then-revalidate boot
loadCommandsWithCache() renders immediately from IndexedDB, then HEAD-revalidates commands.json against a stored ETag + Content-Length and only re-fetches when the artifact changed — a header badge shows fresh / cached / revalidating.
🐍
Reproducible stdlib-only pipeline
Every command traces back to a published source via pure Python 3 standard-library parsers under scripts/; parse.py merges and dedupes by normalized cmd, and clean_titles.py / audit_data_quality.py keep the corpus clean. No runtime dependencies.
Architecture
A static page plus one JSON file
The whole system is one static page plus one JSON file: engineers use the browser app, an offline Python pipeline turns vendor docs and a live FRR lab into commands.json, and GitHub Pages serves the artifacts. index.html is a monolith by file count but cleanly layered into a boot/cache loader, a state + render dispatcher, the filter engine, a concept-align Compare engine, and automation generators.
Engineers use the browser app; an offline Python pipeline turns vendor docs and a live FRR lab into commands.json; GitHub Pages serves the artifacts.
Container & component map
flowchart TB
subgraph BROWSER["index.html - single-file client app"]
direction TB
boot["Data Loader + Cache - loadCommandsWithCache, bootRender, HEAD revalidate"]:::svc
state["Global state + render - DATA, vendor/os/role/cat Sets, replaceChildren"]:::core
filter["Filter + Deep-Link - matches, parseQuery, encodeWorkspace"]:::svc
compare["Compare + Concept Align - conceptKey, lookupConcept, CONCEPT_SYNONYMS 37"]:::accent
auto["Automation Generators - Netmiko, Ansible, NETCONF, Bash"]:::amber
end
json[("commands.json - 52,031 rows")]:::store
persist[["IndexedDB + localStorage - ?ws= base64 deep-link"]]:::ext
json --> boot --> state
state --> filter --> state
state --> compare
state --> auto
boot <--> persist
filter <--> persist
classDef core fill:#15803d,stroke:#34d399,color:#ecfdf5
classDef svc fill:#0e7490,stroke:#5eead4,color:#f0fdfa
classDef accent fill:#0d9488,stroke:#5eead4,color:#f0fdfa
classDef amber fill:#a16207,stroke:#fbbf24,color:#fffbeb
classDef store fill:#0d9488,stroke:#5eead4,color:#f0fdfa
classDef ext fill:#475569,stroke:#94a3b8,color:#f8fafc
A boot/cache loader hydrates DATA; a state + render dispatcher feeds the filter, concept-align Compare, and automation generators, all backed by IndexedDB/localStorage.
How it works
From vendor docs to a live page
An offline, stdlib-only pipeline produces the committed corpus; at runtime the app boots instantly from cache and only re-fetches when the artifact actually changed.
Per-source parsers emit intermediate JSON; parse.py and merge_dcn_corpus.py merge and dedupe by normalized cmd; quality utilities repair/quarantine bad rows before the final committed commands.json.
Runtime boot — cache then revalidate
sequenceDiagram
actor User
participant B as Browser index.html
participant IDB as IndexedDB mvc-cli-cache
participant CDN as GitHub Pages
User->>B: open page
B->>IDB: idbGet cached corpus
alt cache hit
IDB-->>B: cached DATA
B->>B: bootRender, badge cached
end
B->>CDN: HEAD commands.json (ETag + length)
alt changed or no cache
CDN-->>B: new ETag + length
B->>CDN: GET commands.json (no-store)
CDN-->>B: 52,031 records
B->>IDB: idbPut corpus + ETag
B->>B: bootRender, badge fresh
else unchanged
CDN-->>B: 304 same ETag, badge revalidated
end
B-->>User: filtered cards / table / compare
On load the app renders instantly from the IndexedDB cache, then HEAD-revalidates commands.json against a stored ETag and only re-fetches and re-renders when the artifact actually changed.
Tech stack
Zero-dependency by design
No framework, no bundler, no JS dependencies — just the platform and a stdlib-only Python build.
The entire single-file client app (~5,827 lines of vanilla JS): boot/cache loader, global DATA state + render dispatcher, filter/deep-link engine, concept-aligned Compare engine, and automation snippet generators. No framework, no build.
commands.jsonStatic JSON ~17 MB · GitHub Pages
Single source of truth — flat array of 52,031 command records across 17 vendors/tools. Fetched once at boot (cache-then-revalidate) and queried entirely client-side. FRR rows carry optional live/in_docs provenance flags.
scripts/parse.pyPython 3 stdlib
Master merger — generic markdown walker that folds in community sources, seed entries, and all per-source JSONs, deduping globally by normalized cmd to emit commands.json.
scripts/parse_frr.pyPython 3 stdlib
Parses the FRR Master CLI reference JSON (docs ∪ Docker-FRR live scrape) into frr.json, mapping daemons to categories and tagging each row with live/in_docs provenance flags surfaced as a green "live" badge in the UI.
scripts/merge_dcn_corpus.pyPython 3 stdlib (argparse, json, re, pathlib)
Merges the DCN tool's pre-built cli-export.json corpus into commands.json, normalizing vendor labels and roles and deduping by (vendor, normalized cmd) so existing FRR provenance flags survive. Added Microsoft/Linux/Wireshark surfaces.
scripts/clean_titles.pyPython 3 stdlib
Idempotent maintenance utility that derives clean command labels from the cmd field for any record whose title is leaked prose; writes .titlebak backups.
scripts/audit_data_quality.pyPython 3 stdlib
Flags records where description prose has leaked into title/cmd fields and can quarantine unrecoverable rows to keep the corpus clean.
Per-source parsers, one per vendor doc format (Cisco Press chapter+verb regex, Junos two-mode index, Arista bold-backtick, ASA/NX-OS word-boundary role classifier), each emitting an intermediate per-source JSON.
Node-based pure-JS performance + correctness suite that extracts functions (extractPlaceholders, substitutePlaceholders, lookupConcept, CONCEPT_SYNONYMS) directly from index.html and benchmarks them against the production corpus.
configurator.htmlStatic HTML · vanilla JS
Legacy form-based CLI generator kept for archive purposes only — superseded by the cheatsheet's Compare view + Automate drawer; not linked from the live site.
Quickstart
Run it in seconds
No install, no build, no dependencies. Use the hosted demo, or regenerate the corpus locally with Python 3 stdlib.
use it
# Open the live demo (no install) —# https://gesh75.github.io/multivendor-cli-configurator/# Or open index.html directly in any modern browser —# no build, no dependencies