A network scanner written in Rust. CLI, terminal UI, desktop app, and MCP server. One library behind all four.
- Why this exists
- Features
- Screenshots
- Architecture
- Installation
- Usage
- Building
- MCP Server
- Contributing
- License
I wanted my AI agent to answer questions about my local network. Things
like "what's the IP of the device that just joined" or "is port 22 open
on 192.168.1.42". Existing tools work but they aren't great to drive from
an agent. Half a dozen CLI invocations, brittle output parsing, no shared
context. So I built an MCP server first. netscli serve, nine tools by
default (13 in the -pcap build), JSON-RPC over stdio, structured results.
Then the TUI. Coding agents like Claude Code have put real work into autocomplete, command history, in-place progress, and mouse selection that doesn't fight the scrollback. I wanted to see how they do it. So netscli has a proper ratatui TUI with those affordances.
The CLI is simpler. Sometimes you just want netscli scan host --json | jq
and running a full MCP server for that is overkill. Cron jobs and CI
scripts want the same thing.
The desktop app is for when I don't want to open a terminal. Click an
icon, see what's on my network, close it. Because every other surface
already talked to netscli-core, the GUI was mostly a Tauri window over
the same Rust calls.
- Ping, port scan, host discover, subnet sweep, DNS lookup (all record types), reverse DNS, traceroute, ARP table with vendor lookup, mDNS/Bonjour device discovery, interface listing, optional packet capture.
- Four interfaces for the same core:
netscli <cmd>for scripts,netsclialone for a terminal UI with autocomplete and history, a Tauri desktop app for when you want a window, andnetscli servefor Claude / Cursor / any MCP client. --jsonand--yamloutput on every non-interactive subcommand; pipe straight into jq.- Cross-platform. Windows / Linux / macOS binaries in the release matrix. Packet capture is feature-gated so the default binary has zero non-Rust runtime deps.
- Auto-detects a reasonable subnet so
netscli discoverworks with no args.
Dashboard: default interface, live up/down rates, all interfaces at a glance.
Port scan. Results show service names for well-known ports.
DNS lookup. Type and value per row, supports every standard record type.
Interfaces. Each row shows state, MAC, and every assigned address.
brew tap fstubner/tap
brew install netscliwinget install fstubner.netscli # CLI/TUI
winget install fstubner.netscli.gui # Desktop GUIResolves from the official microsoft/winget-pkgs repo (winget ships preinstalled on Windows 10/11). The CLI and desktop app are separate package identifiers so they can be installed independently.
For Windows, winget is the recommended install path. The winget manifest pins the installer URL and verifies the installer SHA256 hash before install. Direct GitHub downloads are available, but the Windows installers are currently unsigned and may show "unknown publisher" or SmartScreen warnings until code signing is added later.
scoop bucket add fstubner https://github.com/fstubner/scoop-bucket
scoop install netscliyay -S netscli-bin # or paru -S netscli-binSource: aur.archlinux.org/packages/netscli-bin.
curl -fsSL https://raw.githubusercontent.com/fstubner/netscli/main/scripts/install.sh | bashThis downloads the latest release binary for your platform and installs it into ~/.local/bin by default.
You can pin a specific release by setting NETSCLI_VERSION (e.g. NETSCLI_VERSION=v0.1.0).
If the release publishes a matching .sha256 asset, the installer will verify the download automatically; you can also set NETSCLI_SHA256 (or NETSCLI_SHA256_URL to fetch a checksum file).
Release assets: Windows x86_64, Linux x86_64/aarch64 (glibc) + Linux x86_64 (musl), macOS x86_64/aarch64.
PCAP-enabled install (optional, adds packet capture support):
curl -fsSL https://raw.githubusercontent.com/fstubner/netscli/main/scripts/install.sh | NETSCLI_PCAP=1 bashThe single NETSCLI_PCAP=1 flag does two things: it downloads the pcap-enabled binary variant and installs the libpcap system library via your package manager. If you already have libpcap installed and don't want the installer touching it, add NETSCLI_SKIP_LIBPCAP=1.
Windows PowerShell (same idea; NETSCLI_PCAP=1 downloads the pcap binary and runs the Npcap installer):
iwr -useb https://raw.githubusercontent.com/fstubner/netscli/main/scripts/install.ps1 | iex
# With PCAP:
$env:NETSCLI_PCAP=1; iwr -useb https://raw.githubusercontent.com/fstubner/netscli/main/scripts/install.ps1 | iexWindows CLI installer details:
- Installs
netscli.exeto$env:USERPROFILE\.cargo\binby default (override withINSTALL_DIR). - Installs from
fstubner/netscliby default (override withREPO) and installs the latest release by default (override withNETSCLI_VERSION). - When
NETSCLI_PCAP=1is set: installs the-pcapasset and runs the Npcap installer (admin required; skip withNETSCLI_SKIP_NPCAP=1). The Npcap installer's Authenticode signature is checked before it is launched, and it is not run at all unless the signer is the Nmap Project — override the expected name withNETSCLI_NPCAP_SIGNERif they publish a new one. - If the release publishes a matching
.sha256asset, the script verifies the download automatically; you can also setNETSCLI_SHA256orNETSCLI_SHA256_URL.
Every CLI and GUI release asset is signed keylessly via Sigstore cosign in CI, using the GitHub Actions OIDC identity — no key management, and the signature is bound to the exact workflow run that built the asset. Each asset ships with a .sig and .pem alongside it. To verify a downloaded asset:
cosign verify-blob \
--signature netscli-linux-x86_64.sig \
--certificate netscli-linux-x86_64.pem \
--certificate-identity-regexp 'https://github.com/fstubner/netscli/.github/workflows/release\.yml@.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
netscli-linux-x86_64Requires the cosign CLI. A successful verification confirms the asset was built and signed by this repository's release workflow and hasn't been tampered with since.
git clone https://github.com/fstubner/netscli.git
cd netscli
cargo build --release -p netscli
sudo cp target/release/netscli /usr/local/bin/cargo install netscliOr install directly from the git tip:
cargo install --git https://github.com/fstubner/netscli netscliPrebuilt installers are attached to every GitHub release as of v0.2.1:
- Windows:
netscli-gui-windows-x86_64.msi— recommended install path iswinget install fstubner.netscli.guibecause winget verifies the published installer hash. Direct MSI installs are currently unsigned and may show Windows warnings. WebView2 ships preinstalled on Windows 10/11; if the app fails to start, install the Evergreen runtime. - macOS:
netscli-gui-macos-aarch64.dmg(Apple Silicon) ornetscli-gui-macos-x86_64.dmg(Intel). Currently unsigned — first launch will show "unverified developer". Right-click → Open to bypass Gatekeeper, or runxattr -dr com.apple.quarantine /Applications/NetsCLI.app. Notarized build is tracked separately. - Linux:
netscli-gui-linux-x86_64.deb(Debian/Ubuntu) ornetscli-gui-linux-x86_64.AppImage(any distro;chmod +xand run).
The published desktop GUI installers are built without packet capture support
so they do not depend on or redistribute Npcap/libpcap. The Packet Capture
tool is visible in the GUI, but it shows setup guidance and cannot run unless
the desktop backend was built with the pcap feature and a working
Npcap/libpcap runtime is installed.
To run it from source:
cd apps/netscli-gui
npm install
npm run tauri:devThat starts the Vite dev server and the app together. Building the Tauri
crate on its own — cargo build -p netscli-gui — gives you a binary that
expects that dev server on localhost:1420 rather than one with the
frontend inside it, so running it directly opens an empty window with no
explanation. Use tauri:dev, or build an installer:
cd apps/netscli-gui
npm install
npm run tauri build
# Installers created in src-tauri/target/release/bundle/Output:
- macOS:
.appbundle insrc-tauri/target/release/bundle/macos/ - Windows:
.exeand.msiinsrc-tauri/target/release/bundle/msi/ - Linux:
.AppImageand.debinsrc-tauri/target/release/bundle/
Run the setup wizard to install optional dependencies:
netscli setupThis will interactively guide you through installing:
libpcap(for packet capture)tcpdump(for PCAP functionality)
DNS lookups use the operating system resolver first. If that resolver returns
an error, NetsCLI may retry public names with Cloudflare DNS so normal internet
lookups still work when the local resolver is flaky. Obvious local/internal
names such as .local, .lan, .home, .internal, .test, and localhost
skip the public fallback.
Set NETSCLI_DNS_FALLBACK=off to disable public DNS fallback entirely.
PCAP capture is optional and disabled in the default builds for portability. To enable it:
-
Via installer (recommended):
NETSCLI_PCAP=1does everything. It picks the pcap-enabled binary variant and installs the system library (libpcapon Linux/macOS, Npcap on Windows).- Add
NETSCLI_SKIP_LIBPCAP=1(POSIX) orNETSCLI_SKIP_NPCAP=1(Windows) if you manage the system library yourself.
- Add
-
From source:
cargo build --features pcap(see Building for the full command with OS-specific deps). -
Desktop GUI: published GUI installers are intentionally non-PCAP. The Packet Capture tab shows setup guidance in those builds. Use
npm run tauri:dev:pcapornpm run tauri build -- --features pcapfor local packet-capture GUI builds. -
Capture parsing: pcap-enabled CLI builds can also summarize existing capture files with
netscli pcap --read <file> --jsonor--yaml. -
On Windows runtime: ensure
wpcap.dllis on PATH. Npcap installs it toC:\Windows\System32\Npcap\which isn't on PATH by default. Add that directory to your PATH, or the installer does it for you when you setNETSCLI_PCAP=1. -
On Windows source builds: install the Npcap SDK as well as the runtime. MSVC needs the SDK import library (
wpcap.lib) at link time:$env:NPCAP_SDK = "C:\tmp\netscli-npcap-sdk" $env:LIB = "$env:NPCAP_SDK\Lib\x64;$env:LIB" $env:INCLUDE = "$env:NPCAP_SDK\Include;$env:INCLUDE" $env:PATH = "C:\Windows\System32\Npcap;$env:PATH" cargo build -p netscli --features pcap .\target\debug\netscli.exe pcap --check
Launch the interactive terminal UI:
netscliKey Features:
- Autocomplete: Type
/to see commands, use Up/Down to navigate, Tab to accept - Command History: Use Up/Down when no suggestions are shown
- Scrollback: PageUp/PageDown/Ctrl+Home/Ctrl+End
- Status footer: Host/IP plus live traffic stats (configurable via
/config) - Cancel: Esc cancels a running command
- Exit: Press Esc or Ctrl+C twice, or type
/exit - Export:
/exportsaves session output to a file - Scrollback/Selection: TUI renders in the main buffer so native scrollback and selection work
- Responsive Layout: UI adapts to terminal resize automatically
Available Commands:
/discover [subnet]- Discover live hosts on a network subnet/scan <host> [ports]- Scan TCP ports on a host (default: common ports)/inspect <host> [ports]- Inspect host (ping + scan + resolve)/sweep [subnet] [ports] [--no-resolve]- Sweep network (discover + scan)/ping <host> [count]- Ping a host/trace <host> [--resolve] [--max-hops <n>]- Trace route (hops)/dns <host> [--record <type>|ALL]- DNS lookup (A/AAAA/CNAME/MX/NS/TXT/SRV/PTR/SOA/CAA)/reverse <ip>- Reverse DNS (PTR) lookup/arp- Show/manage ARP table with vendor information/interfaces- List network interfaces/mdns- Discover devices on the local network via mDNS/DNS-SD (Bonjour)/config- Interactive TUI settings (saved to~/.netscli/tui-settings.json)/export [md|json] [--output <path>]- Export the current session output/pcap ...- Packet capture (pcap-enabled builds only; run/pcap --checkto list interfaces)/help- Show detailed help/exit- Exit the TUI
Run commands directly from the command line:
# Discover hosts on network
netscli discover [subnet] --resolve
# Scan specific ports
netscli scan <host> -p 22,80,443
# Comprehensive host inspection
netscli inspect <host>
# Network sweep (discover + scan)
netscli sweep [subnet] -p 80,443 --resolve
# ARP table
netscli arp
# Ping with count
netscli ping <host> -c 4
# Trace route (hops)
netscli trace <host> --max-hops 20
# DNS lookup (all record types)
netscli dns <host>
# Reverse DNS lookup
netscli reverse <ip>
# List network interfaces
netscli interfaces
# Capture packets (pcap-enabled builds)
netscli pcap --interface "Ethernet" --duration 10 --max-packets 1000 --output capture.pcap
# Summarize an existing capture as a packet table
netscli pcap --read capture.pcap --max-packets 100Most CLI commands support structured JSON output:
netscli discover --json
netscli scan host -p 80 --json
netscli arp --json
netscli pcap --read capture.pcap --jsonMost CLI commands also support YAML:
netscli discover --yaml
netscli scan host -p 80 --yaml
netscli arp --yaml
netscli pcap --read capture.pcap --yamlSupported formats: --json, --yaml
- Rust 1.96.0 (pinned via
rust-toolchain.toml) (install from rustup.rs) - For GUI: Node.js 18+ and npm
# Development
cargo build -p netscli
# Release
cargo build --release -p netscli
# Release with PCAP enabled
cargo build --release -p netscli --features pcap
# Run tests
cargo test --allWindows PCAP source builds require both the Npcap runtime and SDK. Set LIB
to the SDK architecture directory containing wpcap.lib before running
cargo build --features pcap; for 64-bit MSVC this is usually
<Npcap SDK>\Lib\x64. For the core PCAP test target on Windows, run
.\scripts\test-pcap.ps1; it sets LIB, INCLUDE, and the Npcap runtime
PATH from NPCAP_SDK or C:\tmp\netscli-npcap-sdk.
cd apps/netscli-gui
npm install
npm run tauri:dev # Development
npm run tauri build # ProductionDo not launch target/debug/netscli-gui.exe directly after cargo build.
Debug Tauri binaries load the configured devUrl (http://localhost:1420);
if the Vite dev server is not running, WebView2 shows its own localhost
connection error page. Use npm run tauri:dev so Tauri starts and waits for
the frontend server, or build a bundled app with npm run tauri build.
To include PCAP support in the desktop app build:
cd apps/netscli-gui
npm run tauri:dev:pcap # Development with PCAP
npm run tauri build -- --features pcapOn Windows, the same Npcap SDK LIB/INCLUDE setup is required for the
Tauri backend when building with --features pcap. For local development,
scripts/dev-gui-pcap.ps1 sets LIB, INCLUDE, and the Npcap runtime PATH
from NPCAP_SDK or C:\tmp\netscli-npcap-sdk, uses a separate
target-pcap Cargo target directory, then starts the app through Tauri's dev
command. Keeping PCAP GUI builds in a separate target directory avoids
accidentally replacing the normal non-PCAP debug app with a binary that
requires wpcap.dll at process startup.
# Linux (static)
rustup target add x86_64-unknown-linux-musl
cargo build -p netscli --target x86_64-unknown-linux-musl --release
# Windows (from Linux/WSL)
rustup target add x86_64-pc-windows-msvc
cargo build -p netscli --target x86_64-pc-windows-msvc --release
# macOS
rustup target add x86_64-apple-darwin aarch64-apple-darwin
cargo build -p netscli --target x86_64-apple-darwin --releaseTo update the MAC vendor database:
cd scripts
cargo run --bin generate-ouiThis fetches data from IEEE and Wireshark sources and generates crates/netscli-core/data/oui.min.json.gz, which ships embedded in the netscli-core crate.
The MCP server exposes network scanning tools for AI agents via the Model Context Protocol.
Edit ~/.config/Claude/claude_desktop_config.json (Linux):
{
"mcpServers": {
"netscli": {
"command": "netscli",
"args": ["serve"]
}
}
}- Settings -> MCP Servers -> Add MCP Server
- Command:
netscli - Arguments:
serve
netscli mcp-service --install
systemctl --user enable --now netscli-mcp.serviceThe MCP server exposes 9 tools by default (13 in -pcap builds, which add capture_pcap plus three job-based tools for longer captures):
discover_network- Discover live hosts on a network subnetscan_ports- Scan TCP ports on a hostping_host- Ping a host with statisticsdns_lookup- Forward DNS lookup, all record types (reverse lookups are not exposed over MCP)get_arp_table- Get ARP/neighbor table with vendor informationinspect_host- Comprehensive host inspectionsweep_network- Sweep a network (discover hosts then scan ports)list_network_interfaces- List network interfaces with detailsdiscover_mdns- Discover devices via mDNS/DNS-SD (Bonjour), returning hostnames + resolved IPs + service metadatacapture_pcap- Capture network packets to a PCAP file in one blocking call (pcap builds only)start_pcap_capture- Start a packet capture as a background job (pcap builds only)get_pcap_capture_status- Poll the running/completed/failed status of a capture job (pcap builds only)get_pcap_capture_result- Fetch the result of a completed capture job (pcap builds only)
We welcome contributions! Here's how you can help:
git clone https://github.com/fstubner/netscli.git
cd netscli
cargo build -p netscli
cargo test --all- Follow Rust standard formatting:
cargo fmt - Run clippy:
cargo clippy --all-targets -- -D warnings - Write tests for new features
- Update documentation
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes and add tests
- Ensure all tests pass:
cargo test --all - Commit:
git commit -m 'Add amazing feature' - Push:
git push origin feature/amazing-feature - Open a Pull Request
netscli/
|-- crates/
| |-- netscli-core/ # Core network scanning logic
| `-- netscli-mcp/ # MCP server implementation
|-- apps/
| |-- netscli-cli/ # CLI/TUI application
| `-- netscli-gui/ # Tauri desktop GUI
`-- scripts/ # Build/utility scripts
MIT