A fast terminal packet console for live debugging.
Pktbite is a Rust TUI quick triage over SSH or a local terminal.
# time iface proto len source → destination info
42 14:02:11.203 eth0 TCP 74 10.0.0.5:54321 → 1.1.1.1:443 SYN TLS ClientHello SNI=example.com
43 14:02:11.204 eth0 UDP 78 10.0.0.5:53122 → 8.8.8.8:53 DNS query www.example.com
| Tool | Strength | Gap |
|---|---|---|
| tcpdump | Everywhere, scriptable | Hard to browse live |
| Wireshark | Deepest analysis | Heavy RAM/GUI; awkward on servers |
| termshark | Wireshark-in-terminal | Depends on tshark; heavier stack |
| pktbite | Live TUI, fixed memory, simple filters | Shallow decode by design |
Use pktbite to answer “what is talking right now?”, then export a pcap when you need full dissection.
- Live capture on one or more interfaces (each on its own thread)
- UI never blocks on capture; packets flow over a bounded channel
- Ring buffer with fixed capacity (
--buffer-size, default10000) for the live view - When the ring is full, oldest packets are spilled to temporary pcap segments (not lost)
- Spill budget: 10% of total disk capacity (filesystem of the current directory)
- If the filesystem is ≥ 90% full, oldest spill segments are deleted first while new data keeps rolling
- Windowed list rendering (only visible rows) so a full buffer stays responsive
- On exit: choose backup (merged pcap + segment copy) or delete temp spill files
- Channel-backpressure counter (
drop_chan) when the UI cannot keep up - Clean quit restores the terminal and stops capture threads
- Color-coded protocol rows (TCP / UDP / ICMP / ARP)
- Header meters for buffer fill, drops, and flow count
- Adaptive layout by terminal size:
- Wide (≥140 cols): packet list | live detail preview
- Tall: list above detail preview
- Small: compact columns, list only
- Column header bar and single-line function footer (htop-like)
- L2–L4 summaries: Ethernet, IPv4/IPv6, TCP, UDP, ICMP/ICMPv6, ARP
- App-layer hints: DNS, TLS ClientHello SNI, HTTP lines
- TCP hints: SYN / FIN / RST
- Full detail, stream follow, and conversation views
- Capture filter (BPF) at start — presets, custom, or
--filter - Display filter while viewing (
/) — simple host/port/proto/text terms - Offline pcap read (
--read) — no root required - Continuous pcap write (
--write) during live capture - Export currently filtered packets to a pcap file (
e)
| Dependency | Notes |
|---|---|
| Rust | Edition 2021 toolchain (cargo, rustc) |
| libpcap | Packet capture library + headers for build |
| Root / CAP_NET_RAW | Required for live capture only |
# Debian / Ubuntu
sudo apt install libpcap-dev
# Fedora
sudo dnf install libpcap-devel
# Arch
sudo pacman -S libpcapgit clone <repo-url> pktbite
cd pktbite
cargo build --releaseBinary: ./target/release/pktbite
cargo test
cargo run -- --helpsudo ./target/release/pktbiteYou will be prompted for:
- Network interface(s)
- A capture-filter preset (or custom BPF)
# Single interface + BPF (skips preset menu)
sudo pktbite --iface eth0 --filter "port 53"
# Multiple interfaces
sudo pktbite --iface eth0 --iface lo
sudo pktbite --multi
# Larger ring buffer + continuous pcap write
sudo pktbite --iface eth0 --buffer-size 50000 --write /tmp/live.pcap
# All traffic, no filter prompt
sudo pktbite --iface eth0 --no-filter-prompt
# Offline analysis (no root)
pktbite --read ./capture.pcap
# List interfaces
sudo pktbite --list-devices
pktbite --help| Option | Description |
|---|---|
--iface <name> / -i |
Capture on interface (repeatable) |
--multi |
Interactive multi-select of interfaces |
--filter <BPF> |
Capture filter; skips the preset menu |
--no-filter-prompt |
Start with no capture filter |
--buffer-size <N> |
Ring buffer capacity in packets (default: 10000) |
--read <file.pcap> / -r |
Open a pcap offline |
--write <file.pcap> / -w |
Append every live packet to a pcap file |
--list-devices |
Print interfaces and exit |
-h / --help |
Show help |
| Key | Action |
|---|---|
j / k or ↑ / ↓ |
Move one row |
Page Down / Page Up |
Page through list, flows, or scroll detail/stream/help |
Home |
Jump to first packet |
End or f |
Follow live (auto-scroll to newest) |
Enter |
Open packet detail |
Esc |
Back / clear flow focus |
p |
Pause UI (capture still runs) |
/ |
Edit display filter |
x |
Clear display filter |
t |
Conversation / flow view |
s |
Follow stream for selected packet |
g |
Go to packet number |
e |
Export filtered packets to pcap |
c |
Clear ring buffer + flow table |
? |
In-app help |
q or Ctrl+C |
Quit |
Page size follows the visible panel height (adapts when you resize the terminal).
In flows view: Enter focuses the list on that conversation.
There are two different filters. Confusing them is a common source of pain in other tools; the status bar labels them separately.
Applied in the kernel / libpcap before packets enter the buffer. Fewer packets captured = less noise and memory pressure.
Set via:
- Interactive presets at startup (DNS, HTTP, HTTPS, ARP, ICMP, SSH, custom, …)
--filter "tcp port 443"
Examples:
port 53
tcp port 80 or tcp port 443
host 10.0.0.5
arp
icmp or icmp6
Invalid BPF is reported when the capture opens (friendly error from libpcap).
Applied after packets are already in the ring buffer. Use it to search or narrow the view without restarting capture.
Open with /. Whitespace-separated terms are AND-ed.
| Term | Meaning |
|---|---|
tcp udp icmp arp icmpv6 |
Protocol |
host <ip> |
Source or destination IP |
src <ip> / dst <ip> |
Directional IP |
port <n> |
Source or destination port |
sport <n> / dport <n> |
Directional port |
| free text | Substring match on info / DNS / SNI / iface |
Examples:
tcp
host 10.0.0.5
port 443
tcp dport 443
src 192.168.1.1 dport 53
example.com
Typical fields:
| Field | Meaning |
|---|---|
| Device name(s) | Active interface(s) or file:… offline |
LIVE / PAUSED / STOPPED / OFFLINE |
Capture state |
| Mode | LIST, DETAIL, FLOWS, STREAM, … |
pkts |
Total packets accepted into the buffer |
view |
Count matching the current display filter / flow focus |
buf used/cap (%) |
Ring buffer occupancy |
drop_old |
Packets evicted because the buffer was full |
drop_chan |
Packets dropped because the UI channel was full |
follow |
Auto-scroll on/off |
flows |
Number of tracked conversations |
write |
Packets written by --write |
cap:[…] |
Active BPF capture filter |
disp:[…] |
Active display filter |
Non-zero drop_* means you are under load or the buffer is too small — raise --buffer-size, tighten the capture filter, or pause less of the UI work.
NIC(s) ──► capture thread(s) ──► bounded channel ──► TUI loop
│ │ │
│ drop if full ring buffer
│ + flow table
└── optional --write pcap │
▼
list / detail / flows / export
- Capture uses a short pcap read timeout so threads can shut down cleanly.
- Parsing is shallow and local (no tshark dependency).
- Deep analysis path: export pcap → open in Wireshark.
src/
main.rs CLI, live vs offline entry
function.rs Device selection, capture workers, auto-writer
buffer.rs Ring buffer + packet model
parse.rs L2–L4 + DNS / TLS SNI / HTTP
filter.rs Display filter + BPF presets
flow.rs Conversation aggregation
pcap_io.rs pcap read/write
spill.rs temp spill segments, disk budget, exit prompt
tui_set.rs htop-style TUI, adaptive layout, keys
While capturing, the in-memory ring holds the newest packets for the TUI. When it fills, older packets are written under:
./.pktbite-spill-<timestamp>-<pid>/spill-XXXXXX.pcap
| Policy | Behavior |
|---|---|
| Spill budget | ≤ 10% of total capacity of the disk that contains . |
| Segment size | Rotate ~every 8 MiB (granular deletes) |
| Disk pressure | If used space ≥ 90%, delete oldest segments first |
| Auto-export | Segments are valid pcaps; exit Backup also writes merged.pcap |
| Exit prompt | Backup (copy + merge) or Delete temps |
Header status shows spill: packet counts and on-disk size.
- Filters should be forgiving — presets + simple display language; BPF for power users.
- Interop over completeness — pcap in/out instead of reimplementing Wireshark.
- Server-native — works over SSH, no GUI, predictable keys, clean terminal restore.
- Not a full protocol dissector (by design).
- App-layer support is limited to high-signal summaries (DNS, TLS SNI, cleartext HTTP).
- TLS payloads remain encrypted; there is no key-log decryption.
- Capture filter changes require restarting the tool (no mid-session BPF reapply yet).
- pcap format support targets common Ethernet/usec captures; exotic link types may not parse cleanly.
- Windows support is not a current goal.
| Problem | What to try |
|---|---|
| “Root permissions are required…” | Use sudo, or open a file with --read |
| No devices listed | Check interface names; try ip link / --list-devices |
| BPF error on start | Simplify the filter; test with tcpdump -i eth0 <filter> |
| Empty list but traffic exists | Clear display filter (x); check capture filter is not too tight |
High drop_chan / drop_old |
Increase --buffer-size; add a tighter BPF; avoid very busy unfiltered links |
| Terminal messed up after crash | Run reset |
Contributions and issue reports welcome once the project is published. This project is build by AI. but It’s quite useful, so I’m releasing it for others to use.