██╗███████╗████████╗ ██████╗ ██████╗ ██████╗ ███████╗
██║██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗██╔══██╗██╔════╝
██║█████╗ ██║ ██║ ██║██████╔╝██████╔╝╚█████╗
██║██╔══╝ ██║ ██║ ██║██╔═══╝ ██╔══██╗ ╚═══██╗
██║██║ ██║ ╚██████╔╝██║ ██║ ██║██████╔╝
╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚═════╝
cargo install iftoprs
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
█ >> INITIALIZING PACKET INTERCEPT... █
█ >> STATUS: ALL INTERFACES NOMINAL █
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
> FEATURE_DUMP.exe
[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<>>
│ ├── lsof-based socket→process mapping
│ ├── per-process aggregated bandwidth view (Tab key)
│ └── drill-down: Enter on process → 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
│ └── 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
> RENDER_PREVIEW.dat
// LIVE_CAPTURE
> REQUIRED_IMPLANTS.cfg
RUST_VERSION >= 1.85 [2024 edition]
TARGET_OS == macOS || Linux
LIBPCAP == installed (system dependency)
IMPLANT |
PURPOSE |
ratatui 0.30 |
TUI rendering framework |
crossterm 0.29 |
Terminal events + manipulation |
pcap 2.4 |
Packet capture via libpcap |
tokio 1.50 |
Async runtime + channels |
clap 4.6 |
CLI argument parsing |
dns-lookup 3.0 |
Reverse DNS resolution |
regex 1.12 |
Pattern matching for filters |
chrono 0.4 |
Time operations |
anyhow 1.0 |
Error handling |
clap_complete 4 |
Shell completion generation |
serde 1.0 |
Config serialization |
serde_json 1.0 |
JSON streaming output |
toml 1.1 |
Config file format |
dirs 6.0 |
Home directory detection |
> COMPILE_SEQUENCE.sh
cargo build --release
sudo cargo run --release
sudo ./target/release/iftoprs
> CI_AND_QA.sh
GitHub Actions runs on every push and pull request to main, and can be started manually (workflow_dispatch from the Actions tab).
| Job |
Command |
| Format |
cargo --locked fmt --all --check |
| Clippy |
cargo clippy --all-targets --locked -- -D warnings |
| Test |
cargo build --locked and cargo test --locked |
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 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
> CLI_OPTIONS.exe
┌──────────────────────────────────────────────────┐
│ ◈◈◈ COMMAND LINE DECK ◈◈◈ │
└──────────────────────────────────────────────────┘
// CAPTURE
FLAG |
DESCRIPTION |
-i, --interface NAME |
Network interface to monitor |
-f, --filter EXPR |
BPF filter expression (e.g., "tcp port 80") |
-F, --net-filter CIDR |
IPv4 network filter (e.g., "192.168.1.0/24") |
-p, --promiscuous |
Enable promiscuous mode |
// DISPLAY
FLAG |
DESCRIPTION |
-n, --no-dns |
Disable DNS hostname resolution |
-N, --no-port-names |
Disable port-to-service resolution |
-b, --no-bars |
Disable bar graph display |
-B, --bytes |
Display bandwidth in bytes (instead of bits) |
-P, --hide-ports |
Hide ports alongside hosts |
-Z, --no-processes |
Hide process column (shown by default) |
// OUTPUT
FLAG |
DESCRIPTION |
--json |
Stream NDJSON to stdout (no TUI) |
// SYSTEM
FLAG |
DESCRIPTION |
-l, --list-interfaces |
List available interfaces and exit |
--list-colors |
Preview all 31 color themes with swatches |
--completions SHELL |
Generate shell completions (zsh, bash, fish, elvish, powershell) |
-h, --help |
Display help transmission |
-V, --version |
Display version information |
// EXAMPLES
sudo iftoprs -i en0 sudo iftoprs -f "tcp port 443" sudo iftoprs -F 10.0.0.0/8 -B sudo iftoprs -n -N -b sudo iftoprs -Z sudo iftoprs -p iftoprs --completions zsh sudo iftoprs --json sudo iftoprs --json | jq '.flows[0]'
> KEYBIND_MATRIX.dat
┌──────────────────────────────────────────────────┐
│ ◈◈◈ COMMAND INTERFACE ◈◈◈ │
└──────────────────────────────────────────────────┘
// DISPLAY_MODS
KEY |
ACTION |
Tab |
Switch view ── Flows / Processes |
n |
Toggle DNS resolution |
N |
Toggle service name resolution |
t |
Cycle line display ── two-line / one-line / sent / recv |
p |
Toggle port display |
Z |
Toggle process display |
b |
Cycle bar style (gradient / solid / thin / ascii) |
B |
Toggle bytes/bits |
T |
Toggle hover tooltips (right-click still works) |
U |
Toggle cumulative totals |
P |
Pause / resume display (shows overlay) |
x |
Toggle border chrome |
g |
Toggle column header |
f |
Cycle refresh rate ── 1s / 2s / 5s / 10s |
// SORT_PROTOCOL
KEY |
ACTION |
1 |
Sort by 2s average |
2 |
Sort by 10s average |
3 |
Sort by 40s average |
< |
Sort by source name |
> |
Sort by destination name |
o |
Freeze current sort order |
| r | Reverse sort order |
// NAVIGATION
KEY |
ACTION |
j ↓ |
Select next flow |
k ↑ |
Select prev flow |
Ctrl+D |
Half-page down |
Ctrl+U |
Half-page up |
G End |
Jump to last |
Home |
Jump to first |
Esc |
Deselect / clear process filter / close overlay |
Enter |
Drill into selected process (Processes tab) |
// FILTER_OPS
KEY |
ACTION |
/ |
Enter filter mode |
0 |
Clear filter |
Enter |
Confirm filter |
Esc |
Cancel filter |
// THEME_OPS
KEY |
ACTION |
c |
Open theme chooser |
j/k |
Navigate themes |
Enter |
Select theme |
Esc |
Cancel |
// INTERFACE_OPS
KEY |
ACTION |
i |
Open interface chooser (also cycles in popup) |
j/k |
Navigate interfaces |
Enter |
Select interface (saved to config, restart to apply) |
Esc |
Cancel |
// ACTIONS
KEY |
ACTION |
y |
Copy selected flow to clipboard |
F |
Pin/unpin selected flow ★ |
e |
Export flows to ~/.iftoprs.export.txt |
// MOUSE
INPUT |
ACTION |
| Left click |
Select flow row |
| Right click (flow) |
Show TX/RX tooltip with bandwidth, process, sparkline |
| Right click (header) |
Instant segment tooltip (persistent until dismissed) |
| Middle click |
Pin/unpin flow |
| Mouse move |
Dismiss flow tooltip |
| Scroll up/down |
Navigate flows (cycle themes in chooser) |
| Hover header bar |
Segment tooltip after 1s delay (auto-hides after 3s) |
// GENERAL_OPS
KEY |
ACTION |
h ? |
Toggle help HUD |
q |
Disconnect (saves prefs) |
Ctrl+C |
Force disconnect |