README.md

September 5, 2026 · View on GitHub

 ██╗███████╗████████╗ ██████╗ ██████╗ ██████╗ ███████╗
 ██║██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗██╔══██╗██╔════╝
 ██║█████╗     ██║   ██║   ██║██████╔╝██████╔╝╚█████╗
 ██║██╔══╝     ██║   ██║   ██║██╔═══╝ ██╔══██╗ ╚═══██╗
 ██║██║        ██║   ╚██████╔╝██║     ██║  ██║██████╔╝
 ╚═╝╚═╝        ╚═╝    ╚═════╝ ╚═╝     ╚═╝  ╚═╝╚═════╝

CI Crates.io Downloads Docs.rs Docs License: MIT

[SYSTEM://NET_INTERCEPT // JACKING INTO YOUR PACKET STREAM]

"The street finds its own uses for bandwidth."

A neon-drenched terminal UI for real-time bandwidth monitoring. Built in Rust with ratatui + crossterm + pcap. 31 cyberpunk themes, native process attribution (no external tools), JSON streaming, BPF filters, mouse + sparklines, auto-restart capture, hover tooltips.

brew tap MenkeTechnologies/menketech    # one-time
brew install iftoprs                    # via Homebrew tap (recommended)

cargo install iftoprs                   # via crates.io

CLI Help — iftoprs --help

Read the Docs · Engineering Report · strykelang · zshrs · lsofrs


Table of Contents


 ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
 █ >> INITIALIZING PACKET INTERCEPT...                 █
 █ >> STATUS: ALL INTERFACES NOMINAL                   █
 ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

[0x00] FEATURE DUMP

[CAPTURE_ENGINE]
  ├── Live packet capture ─── libpcap / BPF filters
  │   ├── per-flow bandwidth tracking
  │   ├── sliding window averages: 2s / 10s / 40s
  │   ├── cumulative + peak counters
  │   ├── async capture via tokio + mpsc channels
  │   └── auto-restart on transient errors (exponential backoff)

[TELEMETRY_CORE]
  ├── Real-time flow analysis
  │   ├── source ↔ destination pair tracking
  │   ├── protocol detection: TCP / UDP / ICMP / Other
  │   ├── DNS reverse resolution (async, cached)
  │   ├── port-to-service name mapping
  │   └── log10 bandwidth scale: 10b → 1Gb

[PROCESS_INTEL]
  ├── Flow-to-process attribution
  │   ├── PID + process name per connection
  │   ├── background polling via Arc<Mutex<>>
  │   ├── native socket→process mapping (libproc on macOS, /proc on Linux)
  │   ├── per-process aggregated bandwidth view (Tab key)
  │   └── drill-down: Enter on process → filtered flows, Esc to clear

[PROVENANCE_INTEL]
  ├── Publishers view ── third aggregation axis (Tab key)
  │   ├── resolves each flow past pid→name to the binary's code identity
  │   ├── macOS: code-signing Team ID + authority (Security framework)
  │   ├── Linux: owning package (dpkg/rpm) + executable SHA-256
  │   ├── rolls TX/RX up by publisher ("unsigned-binary 40 Mb/s up")
  │   ├── cache keyed by (dev, inode, mtime) — one fingerprint per binary
  │   └── drill-down: Enter on publisher → filtered flows, Esc to clear

[TOOLTIP_SYSTEM]
  ├── Rich contextual tooltips on hover + right-click
  │   ├── right-click flow rows ── TX/RX rates, totals, process, sparkline
  │   ├── hover header bar segments ── 1s delay, 3s auto-hide
  │   ├── right-click header ── instant tooltip, persistent until dismissed
  │   ├── segment tooltips: app info, interface, flows, clock, sort,
  │   │   refresh rate, theme, filter, paused state, help
  │   └── 9-15 lines per segment: config fields, sources, key hints

[SPARKLINE]
  ├── Per-flow bandwidth sparkline (▁▂▃▅▇█)
  │   ├── shown on row below selected flow (40s history)
  │   └── shown in right-click tooltip

[JSON_STREAM]
  ├── --json flag ── headless NDJSON output (no TUI)
  │   ├── streams flow snapshots to stdout
  │   ├── includes rates, totals, process info, publisher/team_id/package
  │   └── pipe to jq, log to file, feed dashboards

[INTERFACE_DECK]
  ├── Sort ─── 2s avg / 10s avg / 40s avg / src name / dst name
  ├── Display ─── bits or bytes / bars on/off / ports on/off
  ├── Line modes ─── two-line / one-line / sent-only / recv-only
  ├── Freeze ─── lock current sort order
  └── Color-coded rate columns ─── yellow(2s) / green(10s) / cyan(40s)

[NET_FILTER]
  ├── BPF filter expressions ─── "tcp port 80", "host 10.0.0.1"
  ├── CIDR network filter ─── auto-detect or manual (-F)
  ├── Promiscuous mode ─── capture all traffic on segment
  └── Interface selection ─── list + choose

[PLATFORM_COMPAT]
  ├── macOS ── SUPPORTED
  ├── Linux ── SUPPORTED
  └── requires libpcap (root/sudo for raw capture)

[THEME_ENGINE]
  ├── 31 builtin cyberpunk color themes (including iftopcolor)
  │   ├── live theme chooser (c key)
  │   ├── swatch preview per theme
  │   └── persistent selection via ~/.iftoprs.conf

[FLOW_SELECTION]
  ├── j/k ── select next/prev flow
  ├── Ctrl+d/u ── half-page scroll
  ├── G/Home ── jump to last/first
  ├── y ── copy selected flow to clipboard
  ├── F ── pin/unpin flow (★ floats to top)
  └── Esc ── deselect

[FILTER_ENGINE]
  ├── / ── live filter by hostname/IP
  ├── 0 ── clear filter
  ├── Ctrl+w ── delete word
  └── Ctrl+k ── kill to end of line

[EXPORT]
  ├── e ── export all flows to ~/.iftoprs.export.txt
  └── includes per-flow rates + TX/RX totals

[ALERT_SYSTEM]
  ├── Bandwidth threshold alerts ── configurable in ~/.iftoprs.conf
  │   ├── red border flash on threshold crossing
  │   ├── terminal bell (\x07) notification
  │   └── status bar message: ⚠ ALERT: hostname rate/s

[CONFIG_ENGINE]
  ├── Auto-save ── every toggle writes to ~/.iftoprs.conf
  ├── Default config ── created on first run if missing
  ├── Reference config ── iftoprs.default.conf with full docs
  └── TOML format ── human-readable, hand-editable

[SHELL_COMPLETION]
  ├── Zsh completions ── completions/_iftoprs
  └── --completions flag ── zsh / bash / fish / elvish / powershell

[0x01] RENDER PREVIEW

// LIVE_CAPTURE

Live Capture View


[0x02] REQUIRED IMPLANTS

RUST_VERSION  >= 1.85  [2024 edition]
TARGET_OS     == macOS || Linux
LIBPCAP       == installed (system dependency)
IMPLANTPURPOSE
ratatui 0.30TUI rendering framework
crossterm 0.29Terminal events + manipulation
pcap 2.4Packet capture via libpcap
tokio 1.51Async runtime + channels
clap 4.6CLI argument parsing
dns-lookup 3.0Reverse DNS resolution
regex 1.12Pattern matching for filters
chrono 0.4Time operations
anyhow 1.0Error handling
clap_complete 4Shell completion generation
serde 1.0Config serialization
serde_json 1.0JSON streaming output
toml 1.1Config file format
dirs 6.0Home directory detection

[0x03] COMPILE SEQUENCE

# ── JACK IN ──────────────────────────────────
cargo build --release
# LTO enabled ── symbols stripped ── lean binary
# ── BOOT THE SNIFFER ─────────────────────────
sudo cargo run --release
# or go direct:
sudo ./target/release/iftoprs
# ── INSTALL MAN PAGES ────────────────────────
sudo cp man/man1/iftoprs.1    /usr/local/share/man/man1/
sudo cp man/man1/iftoprsall.1 /usr/local/share/man/man1/
man iftoprs        # short reference
man iftoprsall     # full reference (keybindings, themes, architecture)

[0x04] CI & QA

GitHub Actions runs on every push and pull request to main, and can be started manually (workflow_dispatch from the Actions tab).

JobCommand
Formatcargo --locked fmt --all --check
Clippycargo clippy --all-targets --locked -- -D warnings
Doccargo doc --locked --no-deps with RUSTDOCFLAGS=-D warnings
Testcargo build --verbose --locked and cargo test --verbose --locked
Docs / Polish / Semantic / Newline + README / Structure gatesshell gate scripts under tests/*.sh (docs HTML hygiene, man pages, final newlines, README structure)

Integration tests in tests/integration.rs execute the built iftoprs binary via CARGO_BIN_EXE_iftoprs (not cargo run), so CLI output is read directly from the process and stays reliable in CI.

The Test job uses Ubuntu and macOS runners. On Linux, apt installs libpcap-dev for the Clippy, Doc, and Test jobs (the Format job does not link pcap and does not install it). The repo rust-toolchain.toml pins stable Rust with rustfmt and clippy so local and CI toolchains stay aligned. The workflow uses least-privilege contents: read permissions and cancels in-progress runs on the same branch when a newer commit is pushed, so redundant builds do not pile up. Jobs have timeouts (format, clippy, and test) so hung runners do not run indefinitely. The test matrix sets fail-fast: false so both operating systems finish even when one fails, which makes cross-platform regressions easier to diagnose.

Run the same checks locally before pushing:

cargo --locked fmt --all --check
cargo clippy --all-targets --locked -- -D warnings
cargo test --locked

[0x05] CLI OPTIONS

 ┌──────────────────────────────────────────────────┐
 │           ◈◈◈  COMMAND LINE DECK  ◈◈◈            │
 └──────────────────────────────────────────────────┘

// CAPTURE

FLAGDESCRIPTION
-i, --interface NAMENetwork interface to monitor
-f, --filter EXPRBPF filter expression (e.g., "tcp port 80")
-F, --net-filter CIDRIPv4 network filter (e.g., "192.168.1.0/24")
-p, --promiscuousEnable promiscuous mode

// DISPLAY

FLAGDESCRIPTION
-n, --no-dnsDisable DNS hostname resolution
-N, --no-port-namesDisable port-to-service resolution
-b, --no-barsDisable bar graph display
-B, --bytesDisplay bandwidth in bytes (instead of bits)
-P, --hide-portsHide ports alongside hosts
-Z, --no-processesHide process column (shown by default)

// OUTPUT

FLAGDESCRIPTION
--jsonStream NDJSON to stdout (no TUI)

// SYSTEM

FLAGDESCRIPTION
-c, --config FILEPath to config file (default: ~/.iftoprs.conf)
-l, --list-interfacesList available interfaces and exit
--list-colorsPreview all 31 color themes with swatches
--completions SHELLGenerate shell completions (zsh, bash, fish, elvish, powershell)
-h, --helpDisplay help transmission
-V, --versionDisplay version information

// EXAMPLES

sudo iftoprs -i en0                    # monitor specific interface
sudo iftoprs -f "tcp port 443"         # filter HTTPS traffic only
sudo iftoprs -F 10.0.0.0/8 -B         # filter private net, show bytes
sudo iftoprs -n -N -b                  # raw IPs, no bars, minimal
sudo iftoprs -Z                        # show process names per flow
sudo iftoprs -p                        # promiscuous mode
iftoprs --completions zsh              # generate zsh completions
sudo iftoprs --json                    # stream NDJSON to stdout
sudo iftoprs --json | jq '.flows[0]'  # pipe to jq for processing
sudo iftoprs --json | jq '.flows[] | {publisher, team_id, package}'  # code provenance

Each NDJSON flow carries the usual rates/totals plus process attribution (process_name, pid) and code provenance. Provenance fields are emitted only when resolved: publisher (rollup label — Team ID, package, or a verdict such as unsigned-binary), team_id (macOS code-signing Team Identifier), and package (Linux dpkg/rpm owning package).


[0x06] KEYBIND MATRIX

 ┌──────────────────────────────────────────────────┐
 │           ◈◈◈  COMMAND INTERFACE  ◈◈◈            │
 └──────────────────────────────────────────────────┘

// DISPLAY_MODS

KEYACTION
TabSwitch view ── Flows / Processes / Publishers
nToggle DNS resolution
NToggle service name resolution
tCycle line display ── two-line / one-line / sent / recv
pToggle port display
ZToggle process display
bCycle bar style (gradient / solid / thin / ascii)
BToggle bytes/bits
TToggle hover tooltips (right-click still works)
UToggle cumulative totals
PPause / resume display (shows overlay)
xToggle border chrome
gToggle column header
fCycle refresh rate ── 1s / 2s / 5s / 10s

// SORT_PROTOCOL

KEYACTION
1Sort by 2s average
2Sort by 10s average
3Sort by 40s average
<Sort by source name
>Sort by destination name
oFreeze current sort order

| r | Reverse sort order |

KEYACTION
j Select next flow
k Select prev flow
Ctrl+DHalf-page down
Ctrl+UHalf-page up
G EndJump to last
HomeJump to first
EscDeselect / clear process or publisher filter / close overlay
EnterDrill into selected process / publisher (Processes / Publishers tab)

// FILTER_OPS

KEYACTION
/Enter filter mode
0Clear filter
EnterConfirm filter
EscCancel filter

// THEME_OPS

KEYACTION
cOpen theme chooser
j/kNavigate themes
EnterSelect theme
EscCancel

// THEME_EDITOR

KEYACTION
COpen the palette editor on the active theme (6 color slots, live preview)
j/k ↓/↑Move between color slots
h/l ←/→Nudge the slot's 256-color index by 1
H/LNudge the slot's index by 10
s S EnterName and save as a custom theme (persisted to ~/.iftoprs.conf)
Esc qCancel and restore the previous palette

// INTERFACE_OPS

KEYACTION
iOpen interface chooser (also cycles in popup)
j/kNavigate interfaces
EnterSelect interface (saved to config, restart to apply)
EscCancel

// ACTIONS

KEYACTION
yCopy selected flow to clipboard (pbcopy/wl-copy/xclip/xsel, falling back to the OSC 52 terminal escape over ssh)
FPin/unpin selected flow ★
eExport flows to ~/.iftoprs.export.txt

// MOUSE

INPUTACTION
Left clickSelect flow row
Right click (flow)Show TX/RX tooltip with bandwidth, process, sparkline
Right click (header)Instant segment tooltip (persistent until dismissed)
Middle clickPin/unpin flow
Mouse moveDismiss flow tooltip
Scroll up/downNavigate flows (cycle themes in chooser)
Hover header barSegment tooltip after 1s delay (auto-hides after 3s)

// GENERAL_OPS

KEYACTION
h ?Toggle help HUD
qDisconnect (saves prefs)
Ctrl+CForce disconnect

[0xFF] LICENSE

MIT License — MenkeTechnologies. See LICENSE.

⟦ END OF LINE ⟧
// THE STREET FINDS ITS OWN USES FOR BANDWIDTH //