multivendor-cli-configurator — architecture Animated terminal banner: a phosphor-green prompt types a network command while 17 vendor chips light up in sequence, connector lines pulse from the command to each matched vendor, a stream of grayed commands scrolls behind, and a counter ticks toward 52,031 commands. router bgp 65001 set protocols ospf area 0 ip route 10.0.0.0/24 nv set interface swp1 config system interface vlan 100 name CORE show ip bgp summary enter candidate router bgp 65001 set protocols ospf area 0 ip route 10.0.0.0/24 nv set interface swp1 config system interface vlan 100 name CORE multivendor-cli — terminal cli ~ $ router bgp 65001 # one intent → 17 vendor syntaxes, concept-aligned corpus 52,031 commands cache-then-revalidate multivendor-cli-configurator 52,000+ CLI commands · 17 vendors · one zero-dependency HTML file Cisco Juniper Arista FRR VyOS Huawei Aruba Extreme FortiOS PAN-OS Mikrotik NVIDIA Nokia SONiC Microsoft Linux Wireshark + Python ETL sources parse + merge commands.json index.html

Multivendor Network CLI Tools

52,000+ CLI commands across 17 vendors and tools in one searchable, comparable, deep-linkable single-file page.

0
CLI commands
0
vendors & tools
0
view modes
0
FRR rows verified live
0
JS dependencies

Overview

One page, every vendor's syntax

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.

index.html (vanilla JS lines)5,827
CONCEPT_SYNONYMS entries37
YANG automation patterns15
FRR lab nodes (Docker)10
commands.json size~17 MB
Roles: router / switch / firewall25,270 / 22,625 / 4,136

Capabilities

Key features

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.

System context

flowchart TB
    eng["Network Engineers - browse, search, compare"]:::actor
    docs["Vendor Docs - Cisco, Junos, EOS, FRR, DCN"]:::source
    lab["10-node Docker FRR Lab - live capture"]:::source
    subgraph SYS["multivendor-cli-configurator"]
      app["index.html - single-file web app"]:::core
      data["commands.json - 52,031 records"]:::store
      pipe["scripts Python ETL - parse, merge, clean"]:::build
    end
    pages["GitHub Pages - static host, auto-deploy"]:::ext
    devices["Target Devices - Netmiko, Ansible, NETCONF"]:::target
    eng -->|"open page"| app
    app -->|"fetch once"| data
    docs --> pipe
    lab --> pipe
    pipe -->|"generates"| data
    pipe -->|"push to main"| pages
    pages -->|"serves"| app
    app -.->|"copy snippets - user-run"| devices
    classDef actor  fill:#0e7490,stroke:#5eead4,color:#f0fdfa
    classDef source fill:#475569,stroke:#94a3b8,color:#f8fafc
    classDef core   fill:#15803d,stroke:#34d399,color:#ecfdf5
    classDef store  fill:#0d9488,stroke:#5eead4,color:#f0fdfa
    classDef build  fill:#a16207,stroke:#fbbf24,color:#fffbeb
    classDef ext    fill:#334155,stroke:#94a3b8,color:#f8fafc
    classDef target fill:#b45309,stroke:#fbbf24,color:#fffbeb

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.

Build & data-flow pipeline

flowchart LR
    src["scripts/sources - vendor books + docs, gitignored"]:::source
    parsers["parse_*.py - encor, junos, arista, frr, cisco extras"]:::build
    inter["per-source JSON - encor.json, junos.json, frr.json"]:::build
    master["parse.py + merge_dcn_corpus.py - merge + dedupe by normalized cmd"]:::accent
    clean["clean_titles.py + audit_data_quality.py - repair, quarantine"]:::accent
    out[("commands.json - 52,031 records")]:::store
    web["index.html - fetch at boot"]:::core
    src --> parsers --> inter --> master --> clean --> out --> web
    classDef source fill:#475569,stroke:#94a3b8,color:#f8fafc
    classDef build  fill:#a16207,stroke:#fbbf24,color:#fffbeb
    classDef accent fill:#0d9488,stroke:#5eead4,color:#f0fdfa
    classDef store  fill:#0d9488,stroke:#5eead4,color:#f0fdfa
    classDef core   fill:#15803d,stroke:#34d399,color:#ecfdf5

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.

Vanilla JavaScript HTML5 CSS grid + custom properties Fetch API (HEAD/GET no-store) IndexedDB (mvc-cli-cache) localStorage + sessionStorage base64 deep-link URLs (?ws=) Python 3 stdlib (json, re, pathlib, argparse) GitHub Pages (static, auto-deploy) Node.js (test harness, assert)

Components

Modules & responsibilities

One single-file client app, one JSON corpus, and a fleet of stdlib-only Python parsers that build it.

ModuleResponsibility
index.htmlVanilla JS · HTML · CSS · Fetch · IndexedDB · localStorageThe 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 PagesSingle 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 stdlibMaster 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 stdlibParses 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 stdlibIdempotent 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 stdlibFlags records where description prose has leaked into title/cmd fields and can quarantine unrecoverable rows to keep the corpus clean.
scripts/parse_encor.py · parse_junos.py · parse_arista.py · parse_cisco_ospf.py · parse_cisco_extras.pyPython 3 stdlibPer-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.
tests/stress_test.jsNode.js assert · process.hrtime.bigintNode-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 JSLegacy 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
regenerate the corpus — Python 3 stdlib only
cd scripts
python3 parse_encor.py
python3 parse_junos.py
python3 parse_arista.py
python3 parse_cisco_ospf.py
python3 parse_cisco_extras.py
python3 parse_frr.py
python3 parse.py   # master merge -> ../commands.json
maintenance + tests
# Maintenance utilities:
python3 scripts/clean_titles.py
python3 scripts/audit_data_quality.py

# Run the Node stress suite:
node tests/stress_test.js